From patchwork Fri Oct 23 17:45:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Kocialkowski X-Patchwork-Id: 11854285 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B0DA8C388F9 for ; Fri, 23 Oct 2020 17:48:03 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 36D1722201 for ; Fri, 23 Oct 2020 17:48:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="W4oAmWsL" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 36D1722201 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=8Zm0VtT7u6u4s+XQEQXA+F+dEKiCXgUa7WvclMz4psk=; b=W4oAmWsLv3zgoTJ5mJlc2BkvV PRbY0/zJVjgiuIvB5BBsCn5KReDDJvoeIViNNBJ/gl749cG3UWYS0lZjHW+IaRAG6Sa1kCzsANZ2D tfPy7DYR/HJ22q9/nThWEc25KEUN38qq5MVnlpoAKEYybC2xFwy8uNGVUOW+gV56+urDPSl4Upc3n EEZjmSq5a48OnmgfN/1/rJ0t8bkRH4E6f8GXtUTnf629zYxN7cppCYzAuYS4K2/9hM5Gw3/jYhuOs 2Qo8c9g6/YEg+IWyGh3aa9PpNMPEwf6F9wAhmzBNyi+4sMu9W4kI9cu9pSYn7PTf546ucJRQZ4nGa 258xU6vgQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW18u-0000lk-Em; Fri, 23 Oct 2020 17:46:20 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW18q-0000ji-Q4 for linux-arm-kernel@lists.infradead.org; Fri, 23 Oct 2020 17:46:18 +0000 X-Originating-IP: 93.29.109.196 Received: from localhost.localdomain (196.109.29.93.rev.sfr.net [93.29.109.196]) (Authenticated sender: paul.kocialkowski@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 2E9101BF203; Fri, 23 Oct 2020 17:46:13 +0000 (UTC) From: Paul Kocialkowski To: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linux-sunxi@googlegroups.com Subject: [PATCH 01/14] phy: Distinguish between Rx and Tx for MIPI D-PHY with submodes Date: Fri, 23 Oct 2020 19:45:33 +0200 Message-Id: <20201023174546.504028-2-paul.kocialkowski@bootlin.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> References: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201023_134616_952440_47E331B2 X-CRM114-Status: GOOD ( 14.56 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hans Verkuil , Philipp Zabel , Thomas Petazzoni , Greg Kroah-Hartman , Helen Koike , Vinod Koul , Maxime Ripard , Kishon Vijay Abraham I , Paul Kocialkowski , Chen-Yu Tsai , Rob Herring , Hans Verkuil , Yong Deng , Sakari Ailus , Mauro Carvalho Chehab , kevin.lhopital@hotmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org As some D-PHY controllers support both Rx and Tx mode, we need a way for users to explicitly request one or the other. For instance, Rx mode can be used along with MIPI CSI-2 while Tx mode can be used with MIPI DSI. Introduce new MIPI D-PHY PHY submodes to use with PHY_MODE_MIPI_DPHY. The default (zero value) is kept to Tx so only the rkisp1 driver, which uses D-PHY in Rx mode, needs to be adapted. Signed-off-by: Paul Kocialkowski Acked-by: Helen Koike --- drivers/staging/media/rkisp1/rkisp1-isp.c | 3 ++- include/linux/phy/phy-mipi-dphy.h | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/rkisp1/rkisp1-isp.c b/drivers/staging/media/rkisp1/rkisp1-isp.c index 6ec1e9816e9f..0afbce00121e 100644 --- a/drivers/staging/media/rkisp1/rkisp1-isp.c +++ b/drivers/staging/media/rkisp1/rkisp1-isp.c @@ -902,7 +902,8 @@ static int rkisp1_mipi_csi2_start(struct rkisp1_isp *isp, phy_mipi_dphy_get_default_config(pixel_clock, isp->sink_fmt->bus_width, sensor->lanes, cfg); - phy_set_mode(sensor->dphy, PHY_MODE_MIPI_DPHY); + phy_set_mode_ext(cdev->dphy, PHY_MODE_MIPI_DPHY, + PHY_MIPI_DPHY_SUBMODE_RX); phy_configure(sensor->dphy, &opts); phy_power_on(sensor->dphy); diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h index a877ffee845d..0f57ef46a8b5 100644 --- a/include/linux/phy/phy-mipi-dphy.h +++ b/include/linux/phy/phy-mipi-dphy.h @@ -6,6 +6,19 @@ #ifndef __PHY_MIPI_DPHY_H_ #define __PHY_MIPI_DPHY_H_ +/** + * enum phy_mipi_dphy_submode - MIPI D-PHY sub-mode + * + * A MIPI D-PHY can be used to transmit or receive data. + * Since some controllers can support both, the direction to enable is specified + * with the PHY sub-mode. Transmit is assumed by default with phy_set_mode. + */ + +enum phy_mipi_dphy_submode { + PHY_MIPI_DPHY_SUBMODE_TX = 0, + PHY_MIPI_DPHY_SUBMODE_RX, +}; + /** * struct phy_configure_opts_mipi_dphy - MIPI D-PHY configuration set * From patchwork Fri Oct 23 17:45:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Kocialkowski X-Patchwork-Id: 11854277 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BD687C55179 for ; Fri, 23 Oct 2020 17:48:20 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4D26622201 for ; Fri, 23 Oct 2020 17:48:20 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="MtYlGcJ+" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4D26622201 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=9VzjDleQaQBswJHcNLcRbkBlyB4bapk4QIeMWLg3+BU=; b=MtYlGcJ+5rHvgLfyKoslTTgVL 4//jSEb9P5dEtdLy+IlIM7DKjA8Dk+5HTLPCBe+Zb9Jgg5yLl8jlo6MaLZhENncYkB83Gs2zCkgVY 47DScRZBNn4grR8hw6obZ2ES8SiRq1FJSgD42iGMmr9tJ9HaZ7aeYYdCkb0h4drPvGn5ySPP8hkew 9tb7Vf3kSotd0YAjMUXeF709HKOU5R0pl67+wIc5ZvVu/dW3e8jH7NbVRSmxN2VRwoc9NdmVvjSVB xTOjUzsMst3EogDkPaavh7ChOnXjFOsEGdhYLCAHsiFVGVAUoe0ANsc3p5jjw0d6kcqEGlUaIm1/J Aq3jrjGUw==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW198-0000sY-Q8; Fri, 23 Oct 2020 17:46:34 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW18r-0000kB-ME for linux-arm-kernel@lists.infradead.org; Fri, 23 Oct 2020 17:46:19 +0000 X-Originating-IP: 93.29.109.196 Received: from localhost.localdomain (196.109.29.93.rev.sfr.net [93.29.109.196]) (Authenticated sender: paul.kocialkowski@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 12F911BF20A; Fri, 23 Oct 2020 17:46:14 +0000 (UTC) From: Paul Kocialkowski To: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linux-sunxi@googlegroups.com Subject: [PATCH 02/14] phy: allwinner: phy-sun6i-mipi-dphy: Support D-PHY Rx mode for MIPI CSI-2 Date: Fri, 23 Oct 2020 19:45:34 +0200 Message-Id: <20201023174546.504028-3-paul.kocialkowski@bootlin.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> References: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201023_134618_144349_660DED0C X-CRM114-Status: GOOD ( 19.71 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hans Verkuil , Philipp Zabel , Thomas Petazzoni , Greg Kroah-Hartman , Helen Koike , Vinod Koul , Maxime Ripard , Kishon Vijay Abraham I , Paul Kocialkowski , Chen-Yu Tsai , Rob Herring , Hans Verkuil , Yong Deng , Sakari Ailus , Mauro Carvalho Chehab , kevin.lhopital@hotmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The Allwinner A31 D-PHY supports both Rx and Tx modes. While the latter is already supported and used for MIPI DSI this adds support for the former, to be used with MIPI CSI-2. This implementation is inspired by the Allwinner BSP implementation. Signed-off-by: Paul Kocialkowski --- drivers/phy/allwinner/phy-sun6i-mipi-dphy.c | 164 +++++++++++++++++++- 1 file changed, 160 insertions(+), 4 deletions(-) diff --git a/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c b/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c index 1fa761ba6cbb..8bcd4bb79f60 100644 --- a/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c +++ b/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c @@ -24,6 +24,14 @@ #define SUN6I_DPHY_TX_CTL_REG 0x04 #define SUN6I_DPHY_TX_CTL_HS_TX_CLK_CONT BIT(28) +#define SUN6I_DPHY_RX_CTL_REG 0x08 +#define SUN6I_DPHY_RX_CTL_EN_DBC BIT(31) +#define SUN6I_DPHY_RX_CTL_RX_CLK_FORCE BIT(24) +#define SUN6I_DPHY_RX_CTL_RX_D3_FORCE BIT(23) +#define SUN6I_DPHY_RX_CTL_RX_D2_FORCE BIT(22) +#define SUN6I_DPHY_RX_CTL_RX_D1_FORCE BIT(21) +#define SUN6I_DPHY_RX_CTL_RX_D0_FORCE BIT(20) + #define SUN6I_DPHY_TX_TIME0_REG 0x10 #define SUN6I_DPHY_TX_TIME0_HS_TRAIL(n) (((n) & 0xff) << 24) #define SUN6I_DPHY_TX_TIME0_HS_PREPARE(n) (((n) & 0xff) << 16) @@ -44,12 +52,29 @@ #define SUN6I_DPHY_TX_TIME4_HS_TX_ANA1(n) (((n) & 0xff) << 8) #define SUN6I_DPHY_TX_TIME4_HS_TX_ANA0(n) ((n) & 0xff) +#define SUN6I_DPHY_RX_TIME0_REG 0x30 +#define SUN6I_DPHY_RX_TIME0_HS_RX_SYNC(n) (((n) & 0xff) << 24) +#define SUN6I_DPHY_RX_TIME0_HS_RX_CLK_MISS(n) (((n) & 0xff) << 16) +#define SUN6I_DPHY_RX_TIME0_LP_RX(n) (((n) & 0xff) << 8) + +#define SUN6I_DPHY_RX_TIME1_REG 0x34 +#define SUN6I_DPHY_RX_TIME1_RX_DLY(n) (((n) & 0xfff) << 20) +#define SUN6I_DPHY_RX_TIME1_LP_RX_ULPS_WP(n) ((n) & 0xfffff) + +#define SUN6I_DPHY_RX_TIME2_REG 0x38 +#define SUN6I_DPHY_RX_TIME2_HS_RX_ANA1(n) (((n) & 0xff) << 8) +#define SUN6I_DPHY_RX_TIME2_HS_RX_ANA0(n) ((n) & 0xff) + +#define SUN6I_DPHY_RX_TIME3_REG 0x40 +#define SUN6I_DPHY_RX_TIME3_LPRST_DLY(n) (((n) & 0xffff) << 16) + #define SUN6I_DPHY_ANA0_REG 0x4c #define SUN6I_DPHY_ANA0_REG_PWS BIT(31) #define SUN6I_DPHY_ANA0_REG_DMPC BIT(28) #define SUN6I_DPHY_ANA0_REG_DMPD(n) (((n) & 0xf) << 24) #define SUN6I_DPHY_ANA0_REG_SLV(n) (((n) & 7) << 12) #define SUN6I_DPHY_ANA0_REG_DEN(n) (((n) & 0xf) << 8) +#define SUN6I_DPHY_ANA0_REG_SFB(n) (((n) & 3) << 2) #define SUN6I_DPHY_ANA1_REG 0x50 #define SUN6I_DPHY_ANA1_REG_VTTMODE BIT(31) @@ -92,6 +117,8 @@ struct sun6i_dphy { struct phy *phy; struct phy_configure_opts_mipi_dphy config; + + int submode; }; static int sun6i_dphy_init(struct phy *phy) @@ -105,6 +132,18 @@ static int sun6i_dphy_init(struct phy *phy) return 0; } +static int sun6i_dphy_set_mode(struct phy *phy, enum phy_mode mode, int submode) +{ + struct sun6i_dphy *dphy = phy_get_drvdata(phy); + + if (mode != PHY_MODE_MIPI_DPHY) + return -EINVAL; + + dphy->submode = submode; + + return 0; +} + static int sun6i_dphy_configure(struct phy *phy, union phy_configure_opts *opts) { struct sun6i_dphy *dphy = phy_get_drvdata(phy); @@ -119,9 +158,8 @@ static int sun6i_dphy_configure(struct phy *phy, union phy_configure_opts *opts) return 0; } -static int sun6i_dphy_power_on(struct phy *phy) +static int sun6i_dphy_tx_power_on(struct sun6i_dphy *dphy) { - struct sun6i_dphy *dphy = phy_get_drvdata(phy); u8 lanes_mask = GENMASK(dphy->config.lanes - 1, 0); regmap_write(dphy->regs, SUN6I_DPHY_TX_CTL_REG, @@ -211,12 +249,129 @@ static int sun6i_dphy_power_on(struct phy *phy) return 0; } +static int sun6i_dphy_rx_power_on(struct sun6i_dphy *dphy) +{ + /* Physical clock rate is actually half of symbol rate with DDR. */ + unsigned long mipi_symbol_rate = dphy->config.hs_clk_rate; + unsigned long dphy_clk_rate; + unsigned int rx_dly; + unsigned int lprst_dly; + u32 value; + + dphy_clk_rate = clk_get_rate(dphy->mod_clk); + if (!dphy_clk_rate) + return -1; + + /* Hardcoded timing parameters from the Allwinner BSP. */ + regmap_write(dphy->regs, SUN6I_DPHY_RX_TIME0_REG, + SUN6I_DPHY_RX_TIME0_HS_RX_SYNC(255) | + SUN6I_DPHY_RX_TIME0_HS_RX_CLK_MISS(255) | + SUN6I_DPHY_RX_TIME0_LP_RX(255)); + + /* + * Formula from the Allwinner BSP, with hardcoded coefficients + * (probably internal divider/multiplier). + */ + rx_dly = 8 * (unsigned int)(dphy_clk_rate / (mipi_symbol_rate / 8)); + + /* + * The Allwinner BSP has an alternative formula for LP_RX_ULPS_WP: + * lp_ulps_wp_cnt = lp_ulps_wp_ms * lp_clk / 1000 + * but does not use it and hardcodes 255 instead. + */ + regmap_write(dphy->regs, SUN6I_DPHY_RX_TIME1_REG, + SUN6I_DPHY_RX_TIME1_RX_DLY(rx_dly) | + SUN6I_DPHY_RX_TIME1_LP_RX_ULPS_WP(255)); + + /* HS_RX_ANA0 value is hardcoded in the Allwinner BSP. */ + regmap_write(dphy->regs, SUN6I_DPHY_RX_TIME2_REG, + SUN6I_DPHY_RX_TIME2_HS_RX_ANA0(4)); + + /* + * Formula from the Allwinner BSP, with hardcoded coefficients + * (probably internal divider/multiplier). + */ + lprst_dly = 4 * (unsigned int)(dphy_clk_rate / (mipi_symbol_rate / 2)); + + regmap_write(dphy->regs, SUN6I_DPHY_RX_TIME3_REG, + SUN6I_DPHY_RX_TIME3_LPRST_DLY(lprst_dly)); + + /* Analog parameters are hardcoded in the Allwinner BSP. */ + regmap_write(dphy->regs, SUN6I_DPHY_ANA0_REG, + SUN6I_DPHY_ANA0_REG_PWS | + SUN6I_DPHY_ANA0_REG_SLV(7) | + SUN6I_DPHY_ANA0_REG_SFB(2)); + + regmap_write(dphy->regs, SUN6I_DPHY_ANA1_REG, + SUN6I_DPHY_ANA1_REG_SVTT(4)); + + regmap_write(dphy->regs, SUN6I_DPHY_ANA4_REG, + SUN6I_DPHY_ANA4_REG_DMPLVC | + SUN6I_DPHY_ANA4_REG_DMPLVD(1)); + + regmap_write(dphy->regs, SUN6I_DPHY_ANA2_REG, + SUN6I_DPHY_ANA2_REG_ENIB); + + regmap_write(dphy->regs, SUN6I_DPHY_ANA3_REG, + SUN6I_DPHY_ANA3_EN_LDOR | + SUN6I_DPHY_ANA3_EN_LDOC | + SUN6I_DPHY_ANA3_EN_LDOD); + + /* + * Delay comes from the Allwinner BSP, likely for internal regulator + * ramp-up. + */ + udelay(3); + + value = SUN6I_DPHY_RX_CTL_EN_DBC | SUN6I_DPHY_RX_CTL_RX_CLK_FORCE; + + /* + * Rx data lane force-enable bits are used as regular RX enable by the + * Allwinner BSP. + */ + if (dphy->config.lanes >= 1) + value |= SUN6I_DPHY_RX_CTL_RX_D0_FORCE; + if (dphy->config.lanes >= 2) + value |= SUN6I_DPHY_RX_CTL_RX_D1_FORCE; + if (dphy->config.lanes >= 3) + value |= SUN6I_DPHY_RX_CTL_RX_D2_FORCE; + if (dphy->config.lanes == 4) + value |= SUN6I_DPHY_RX_CTL_RX_D3_FORCE; + + regmap_write(dphy->regs, SUN6I_DPHY_RX_CTL_REG, value); + + regmap_write(dphy->regs, SUN6I_DPHY_GCTL_REG, + SUN6I_DPHY_GCTL_LANE_NUM(dphy->config.lanes) | + SUN6I_DPHY_GCTL_EN); + + return 0; +} + +static int sun6i_dphy_power_on(struct phy *phy) +{ + struct sun6i_dphy *dphy = phy_get_drvdata(phy); + + switch (dphy->submode) { + case PHY_MIPI_DPHY_SUBMODE_TX: + return sun6i_dphy_tx_power_on(dphy); + case PHY_MIPI_DPHY_SUBMODE_RX: + return sun6i_dphy_rx_power_on(dphy); + default: + return -EINVAL; + } +} + static int sun6i_dphy_power_off(struct phy *phy) { struct sun6i_dphy *dphy = phy_get_drvdata(phy); - regmap_update_bits(dphy->regs, SUN6I_DPHY_ANA1_REG, - SUN6I_DPHY_ANA1_REG_VTTMODE, 0); + regmap_write(dphy->regs, SUN6I_DPHY_GCTL_REG, 0); + + regmap_write(dphy->regs, SUN6I_DPHY_ANA0_REG, 0); + regmap_write(dphy->regs, SUN6I_DPHY_ANA1_REG, 0); + regmap_write(dphy->regs, SUN6I_DPHY_ANA2_REG, 0); + regmap_write(dphy->regs, SUN6I_DPHY_ANA3_REG, 0); + regmap_write(dphy->regs, SUN6I_DPHY_ANA4_REG, 0); return 0; } @@ -234,6 +389,7 @@ static int sun6i_dphy_exit(struct phy *phy) static const struct phy_ops sun6i_dphy_ops = { + .set_mode = sun6i_dphy_set_mode, .configure = sun6i_dphy_configure, .power_on = sun6i_dphy_power_on, .power_off = sun6i_dphy_power_off, From patchwork Fri Oct 23 17:45:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Kocialkowski X-Patchwork-Id: 11854281 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B5B74C4363A for ; Fri, 23 Oct 2020 17:48:20 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 437EF21582 for ; Fri, 23 Oct 2020 17:48:20 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="E5btffOO" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 437EF21582 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=DPUcGQdW/5oemMkMRPJDdnCnrJ/1KAb9wfW2CQ/Q8rs=; b=E5btffOOYg1ZjfZH6I+2gE85a hblwS1Jqn5Frqr2RjqIkFGQD9GojRgSrgbQunUoSdY3rFUYWxtRQzR8YkY1XUrAaE5NEA5+sFJLkk BQVdjubkoQtGXDnHbK1fNH8kBb1U8ig6Hu61iyTZXm7ExGUqwPCy8T3jw0F7BsOIf/lkaE0m1hh9p ZXz/OX2XJFpvkp/lBbmOcPT4CH1ZBOZTxWXZLeiFN9+YQVD6UN4ys3xItzkSSEGa62ikST2jmq/mb h/JLvqhO4wClbax4dh0OgsMLAoFbZRFN02654zyeZRi6dwZDrcB8aPW4X5gCh9VYmFkDUWPNfQ+YL Rfmd5fr3g==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW19H-0000wQ-9A; Fri, 23 Oct 2020 17:46:43 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW18t-0000l3-DX for linux-arm-kernel@lists.infradead.org; Fri, 23 Oct 2020 17:46:20 +0000 X-Originating-IP: 93.29.109.196 Received: from localhost.localdomain (196.109.29.93.rev.sfr.net [93.29.109.196]) (Authenticated sender: paul.kocialkowski@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id D7A2B1BF206; Fri, 23 Oct 2020 17:46:16 +0000 (UTC) From: Paul Kocialkowski To: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linux-sunxi@googlegroups.com Subject: [PATCH 03/14] media: sun6i-csi: Support an optional dedicated memory pool Date: Fri, 23 Oct 2020 19:45:35 +0200 Message-Id: <20201023174546.504028-4-paul.kocialkowski@bootlin.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> References: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201023_134619_572392_590476A8 X-CRM114-Status: GOOD ( 16.39 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hans Verkuil , Philipp Zabel , Thomas Petazzoni , Greg Kroah-Hartman , Helen Koike , Vinod Koul , Maxime Ripard , Kishon Vijay Abraham I , Paul Kocialkowski , Chen-Yu Tsai , Rob Herring , Hans Verkuil , Yong Deng , Sakari Ailus , Mauro Carvalho Chehab , kevin.lhopital@hotmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This allows selecting a dedicated CMA memory pool (specified via device-tree) instead of the default one. Signed-off-by: Paul Kocialkowski --- drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c index 28e89340fed9..5d2389a5cd17 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -849,6 +850,12 @@ static int sun6i_csi_resource_request(struct sun6i_csi_dev *sdev, return PTR_ERR(sdev->regmap); } + ret = of_reserved_mem_device_init(&pdev->dev); + if (ret && ret != -ENODEV) { + dev_err(&pdev->dev, "Unable to init reserved memory\n"); + return ret; + } + sdev->clk_mod = devm_clk_get(&pdev->dev, "mod"); if (IS_ERR(sdev->clk_mod)) { dev_err(&pdev->dev, "Unable to acquire csi clock\n"); @@ -917,6 +924,7 @@ static int sun6i_csi_remove(struct platform_device *pdev) struct sun6i_csi_dev *sdev = platform_get_drvdata(pdev); sun6i_csi_v4l2_cleanup(&sdev->csi); + of_reserved_mem_device_release(sdev->dev); return 0; } From patchwork Fri Oct 23 17:45:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Kocialkowski X-Patchwork-Id: 11854279 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 59FEEC388F9 for ; Fri, 23 Oct 2020 17:48:38 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E1AB82192A for ; Fri, 23 Oct 2020 17:48:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="wqxCG6Hl" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E1AB82192A Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=QOBKx9JUKXrvlerpkPnUysVtWycCU5gLy+tczcgNJl8=; b=wqxCG6HlQwNh40Zzztmdz3kqO uKuUOQ1hRDGAJyfrF2io0w9vAbQyqgS61/jJYRKmRT8UTk2RLgWfPK6+J1Hn4XRof+UXtcslUivCf 7mInOd7Jjr/ZKDuIOfnFDi3VAlQYQ8hE+pLxlkkQPOzLg/wngPmhR1pp/rhro/TID3uRm8kTCC4s3 5YGXHuZNS/7kVHaOtSPrqhmhHt/K7nFEFkAtIDkkriH1Ar0AODX3jj42++XiaXhjRFUNvGw1s0E/Y 3swjOTPZ4vnpN1+k6J6c+VqFN5OIxe7roagqA9NulL7M7LJHHwzt9Y4fy+LwWY2u2F+h5Ef/C4kj0 ndjYsX5Nw==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW19R-00010j-86; Fri, 23 Oct 2020 17:46:53 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW18v-0000lw-Of for linux-arm-kernel@lists.infradead.org; Fri, 23 Oct 2020 17:46:25 +0000 X-Originating-IP: 93.29.109.196 Received: from localhost.localdomain (196.109.29.93.rev.sfr.net [93.29.109.196]) (Authenticated sender: paul.kocialkowski@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id A2EDB1BF208; Fri, 23 Oct 2020 17:46:18 +0000 (UTC) From: Paul Kocialkowski To: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linux-sunxi@googlegroups.com Subject: [PATCH 04/14] media: sun6i-csi: Fix the image storage bpp for 10/12-bit Bayer formats Date: Fri, 23 Oct 2020 19:45:36 +0200 Message-Id: <20201023174546.504028-5-paul.kocialkowski@bootlin.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> References: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201023_134622_026334_06415BF5 X-CRM114-Status: GOOD ( 14.81 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?b?S8OpdmluIEwnaMO0cGl0YWw=?= , Hans Verkuil , Philipp Zabel , Thomas Petazzoni , Greg Kroah-Hartman , Helen Koike , Vinod Koul , Maxime Ripard , Kishon Vijay Abraham I , Paul Kocialkowski , Chen-Yu Tsai , Rob Herring , Hans Verkuil , Yong Deng , Sakari Ailus , Mauro Carvalho Chehab , kevin.lhopital@hotmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Both 10 and 12-bit Bayer formats are stored aligned as 16-bit values in memory, not unaligned 10 or 12 bits. Since the current code for retreiving the bpp is used only to calculate the memory storage size of the picture (which is what pixel formats describe, unlike media bus formats), fix it there. Fixes: 5cc7522d8965 ("media: sun6i: Add support for Allwinner CSI V3s") Co-developed-by: Kévin L'hôpital Signed-off-by: Kévin L'hôpital Signed-off-by: Paul Kocialkowski --- .../platform/sunxi/sun6i-csi/sun6i_csi.h | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h index c626821aaedb..7f2be70ae641 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h @@ -86,7 +86,7 @@ void sun6i_csi_update_buf_addr(struct sun6i_csi *csi, dma_addr_t addr); */ void sun6i_csi_set_stream(struct sun6i_csi *csi, bool enable); -/* get bpp form v4l2 pixformat */ +/* get memory storage bpp from v4l2 pixformat */ static inline int sun6i_csi_get_bpp(unsigned int pixformat) { switch (pixformat) { @@ -96,15 +96,6 @@ static inline int sun6i_csi_get_bpp(unsigned int pixformat) case V4L2_PIX_FMT_SRGGB8: case V4L2_PIX_FMT_JPEG: return 8; - case V4L2_PIX_FMT_SBGGR10: - case V4L2_PIX_FMT_SGBRG10: - case V4L2_PIX_FMT_SGRBG10: - case V4L2_PIX_FMT_SRGGB10: - return 10; - case V4L2_PIX_FMT_SBGGR12: - case V4L2_PIX_FMT_SGBRG12: - case V4L2_PIX_FMT_SGRBG12: - case V4L2_PIX_FMT_SRGGB12: case V4L2_PIX_FMT_HM12: case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: @@ -121,6 +112,15 @@ static inline int sun6i_csi_get_bpp(unsigned int pixformat) case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_RGB565X: return 16; + case V4L2_PIX_FMT_SBGGR10: + case V4L2_PIX_FMT_SGBRG10: + case V4L2_PIX_FMT_SGRBG10: + case V4L2_PIX_FMT_SRGGB10: + case V4L2_PIX_FMT_SBGGR12: + case V4L2_PIX_FMT_SGBRG12: + case V4L2_PIX_FMT_SGRBG12: + case V4L2_PIX_FMT_SRGGB12: + return 16; case V4L2_PIX_FMT_RGB24: case V4L2_PIX_FMT_BGR24: return 24; From patchwork Fri Oct 23 17:45:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Kocialkowski X-Patchwork-Id: 11854287 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7E67C4363A for ; Fri, 23 Oct 2020 17:48:39 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 63A0521582 for ; Fri, 23 Oct 2020 17:48:39 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="o0R6TiW3" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 63A0521582 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=N8faFotG/ZccEp1SOCUBerkEFwCh1OvZqggB3GGGef8=; b=o0R6TiW3GYMEvoKRc5Q3QWMDA yQVzCp0TN+Nmi016rQlQGFfcDlbNHZmeHR9PLtD9DO2M7BMpOMiHj/FX8vhI/SGxHylOXLhsax72S QgwTMzT8v3gq4VKjamScL2A9zObNB50jVJFjiq19O+2FqFKu+5i3UprBaI8Xw5b058SPPaT3tSxML 6T/wNpRuii6XJB7bQldbmr1FFqzfSZo0+m3wuqmOPUGnvj+X5DKEX4y1Wq1vAOSfoIda5EDtM8yxi oC5Jcr/x4cx9SgxDm465Oxiq52OXVSlD3q8Ft2VBjQbiof4LHSSHuUQCWouxh4v2gmUtIgMpL8UA3 q1ljvWdvA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW19e-00014G-0U; Fri, 23 Oct 2020 17:47:06 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW18x-0000nA-Ta for linux-arm-kernel@lists.infradead.org; Fri, 23 Oct 2020 17:46:27 +0000 X-Originating-IP: 93.29.109.196 Received: from localhost.localdomain (196.109.29.93.rev.sfr.net [93.29.109.196]) (Authenticated sender: paul.kocialkowski@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id EB05A1BF20D; Fri, 23 Oct 2020 17:46:20 +0000 (UTC) From: Paul Kocialkowski To: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linux-sunxi@googlegroups.com Subject: [PATCH 05/14] media: sun6i-csi: Only configure the interface data width for parallel Date: Fri, 23 Oct 2020 19:45:37 +0200 Message-Id: <20201023174546.504028-6-paul.kocialkowski@bootlin.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> References: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201023_134624_210860_996DAFC1 X-CRM114-Status: GOOD ( 15.40 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?b?S8OpdmluIEwnaMO0cGl0YWw=?= , Hans Verkuil , Philipp Zabel , Thomas Petazzoni , Greg Kroah-Hartman , Helen Koike , Vinod Koul , Maxime Ripard , Kishon Vijay Abraham I , Paul Kocialkowski , Chen-Yu Tsai , Rob Herring , Hans Verkuil , Yong Deng , Sakari Ailus , Mauro Carvalho Chehab , kevin.lhopital@hotmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Bits related to the interface data width do not have any effect when the CSI controller is taking input from the MIPI CSI-2 controller. In prevision of adding support for this case, set these bits conditionally so there is no ambiguity. Co-developed-by: Kévin L'hôpital Signed-off-by: Kévin L'hôpital Signed-off-by: Paul Kocialkowski --- .../platform/sunxi/sun6i-csi/sun6i_csi.c | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c index 5d2389a5cd17..a876a05ea3c7 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c @@ -378,8 +378,13 @@ static void sun6i_csi_setup_bus(struct sun6i_csi_dev *sdev) unsigned char bus_width; u32 flags; u32 cfg; + bool input_parallel = false; bool input_interlaced = false; + if (endpoint->bus_type == V4L2_MBUS_PARALLEL || + endpoint->bus_type == V4L2_MBUS_BT656) + input_parallel = true; + if (csi->config.field == V4L2_FIELD_INTERLACED || csi->config.field == V4L2_FIELD_INTERLACED_TB || csi->config.field == V4L2_FIELD_INTERLACED_BT) @@ -395,6 +400,26 @@ static void sun6i_csi_setup_bus(struct sun6i_csi_dev *sdev) CSI_IF_CFG_HREF_POL_MASK | CSI_IF_CFG_FIELD_MASK | CSI_IF_CFG_SRC_TYPE_MASK); + if (input_parallel) { + switch (bus_width) { + case 8: + cfg |= CSI_IF_CFG_IF_DATA_WIDTH_8BIT; + break; + case 10: + cfg |= CSI_IF_CFG_IF_DATA_WIDTH_10BIT; + break; + case 12: + cfg |= CSI_IF_CFG_IF_DATA_WIDTH_12BIT; + break; + case 16: /* No need to configure DATA_WIDTH for 16bit */ + break; + default: + dev_warn(sdev->dev, "Unsupported bus width: %u\n", + bus_width); + break; + } + } + if (input_interlaced) cfg |= CSI_IF_CFG_SRC_TYPE_INTERLACED; else @@ -440,23 +465,6 @@ static void sun6i_csi_setup_bus(struct sun6i_csi_dev *sdev) break; } - switch (bus_width) { - case 8: - cfg |= CSI_IF_CFG_IF_DATA_WIDTH_8BIT; - break; - case 10: - cfg |= CSI_IF_CFG_IF_DATA_WIDTH_10BIT; - break; - case 12: - cfg |= CSI_IF_CFG_IF_DATA_WIDTH_12BIT; - break; - case 16: /* No need to configure DATA_WIDTH for 16bit */ - break; - default: - dev_warn(sdev->dev, "Unsupported bus width: %u\n", bus_width); - break; - } - regmap_write(sdev->regmap, CSI_IF_CFG_REG, cfg); } From patchwork Fri Oct 23 17:45:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Kocialkowski X-Patchwork-Id: 11854291 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EDE02C4363A for ; Fri, 23 Oct 2020 17:49:07 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6B0B72168B for ; Fri, 23 Oct 2020 17:49:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="e/dznBD+" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6B0B72168B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=dFS3UvAx6iim5p6PBv/2zA3VVMh9jeE08VoFDznrMv8=; b=e/dznBD+NtslUsBs9z/ZQ+JAi MR2GV8aejzHgM3he4f1XGFTKXgV9/FFBEey4q1T/rVJxjzqhYJ03jVFPydMju8OS9k7GHRk1u22XD uUFI/beKKtpioUylUx7lu+aBVi/clEg9Bn1hUuWYcTc7eacgZAmkUOve0SQyVlZDRqJk0lZpSgwUy Rvg+jx+cp7r7mtcQLV9Tk3FPr7CslbuBpLLWbjazy0hhkTyA1ljJM/BRpFMNLrQRb/11aLkWB6F1b nVNFuOIzvsAxnL37dzgoNFK/xZlzpW7BIqremcGqkcftMTIiknC5KBbVG58+lAdH20C13aYdGB/PT QGxzjcHAg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW19m-00016H-Aw; Fri, 23 Oct 2020 17:47:14 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW18z-0000o1-Tw for linux-arm-kernel@lists.infradead.org; Fri, 23 Oct 2020 17:46:28 +0000 X-Originating-IP: 93.29.109.196 Received: from localhost.localdomain (196.109.29.93.rev.sfr.net [93.29.109.196]) (Authenticated sender: paul.kocialkowski@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 1C0101BF20F; Fri, 23 Oct 2020 17:46:23 +0000 (UTC) From: Paul Kocialkowski To: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linux-sunxi@googlegroups.com Subject: [PATCH 06/14] media: sun6i-csi: Support feeding from the MIPI CSI-2 controller Date: Fri, 23 Oct 2020 19:45:38 +0200 Message-Id: <20201023174546.504028-7-paul.kocialkowski@bootlin.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> References: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201023_134626_175841_D21F1C5A X-CRM114-Status: GOOD ( 13.38 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?b?S8OpdmluIEwnaMO0cGl0YWw=?= , Hans Verkuil , Philipp Zabel , Thomas Petazzoni , Greg Kroah-Hartman , Helen Koike , Vinod Koul , Maxime Ripard , Kishon Vijay Abraham I , Paul Kocialkowski , Chen-Yu Tsai , Rob Herring , Hans Verkuil , Yong Deng , Sakari Ailus , Mauro Carvalho Chehab , kevin.lhopital@hotmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The A31 CSI controller supports MIPI CSI-2, through a dedicated controller. The MIPI CSI-2 controller (which differs between A31 and A83T) is supported as a separate driver and connected through the fwnode graph. The two controllers are likely connected through some kind of FIFO, so the CSI controller doesn't have much to do itself except for selecting the MIPI CSI-2 input. Co-developed-by: Kévin L'hôpital Signed-off-by: Kévin L'hôpital Signed-off-by: Paul Kocialkowski --- drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c index a876a05ea3c7..e770153cf3ab 100644 --- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c +++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c @@ -459,6 +459,9 @@ static void sun6i_csi_setup_bus(struct sun6i_csi_dev *sdev) if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) cfg |= CSI_IF_CFG_CLK_POL_FALLING_EDGE; break; + case V4L2_MBUS_CSI2_DPHY: + cfg |= CSI_IF_CFG_MIPI_IF_MIPI; + break; default: dev_warn(sdev->dev, "Unsupported bus type: %d\n", endpoint->bus_type); @@ -713,6 +716,7 @@ static int sun6i_csi_fwnode_parse(struct device *dev, } switch (vep->bus_type) { + case V4L2_MBUS_CSI2_DPHY: case V4L2_MBUS_PARALLEL: case V4L2_MBUS_BT656: csi->v4l2_ep = *vep; From patchwork Fri Oct 23 17:45:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Kocialkowski X-Patchwork-Id: 11854295 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 08E6FC4363A for ; Fri, 23 Oct 2020 17:49:12 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3D3D72168B for ; Fri, 23 Oct 2020 17:49:11 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="atObk7WL" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3D3D72168B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=3ZaJwP8jHtjUFcbENKic23y379k2mruUxOUeq5YjwSo=; b=atObk7WLJgjviex4pSes3xk5s 486VOR0i7MwJj6JkTiTNrTmq44eKm0P5ctdYYN/yV+AAW1v3j7Jt5VNW9rU191VDyqBCPADi+M4aX FHt6URB6R31bBx/JdakCf+HVZXc8OmKBNFr+RGwOPWfjPgKLm4ZevwbmvMk1v++QGy3BY7JKpzHIL fXjB7GeOFrELqHpI8q5d1blWQRvVKUBo50cw1sq07lCO2t9X2JhCLw1XulaIy6Fc/22Y6MHpdWt7o ArwDqw1ZuXOq7jA/A+S6dqZRYF3NRbW1Fbl1VULZaWeCeAkHOWHc+K7W34PV5Z2FUag85ysDrOvOL /hEt8hUNw==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW19v-0001Ao-Pf; Fri, 23 Oct 2020 17:47:23 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW191-0000ob-Ly for linux-arm-kernel@lists.infradead.org; Fri, 23 Oct 2020 17:46:30 +0000 X-Originating-IP: 93.29.109.196 Received: from localhost.localdomain (196.109.29.93.rev.sfr.net [93.29.109.196]) (Authenticated sender: paul.kocialkowski@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 0D4931BF20C; Fri, 23 Oct 2020 17:46:24 +0000 (UTC) From: Paul Kocialkowski To: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linux-sunxi@googlegroups.com Subject: [PATCH 07/14] dt-bindings: media: i2c: Add A31 MIPI CSI-2 bindings documentation Date: Fri, 23 Oct 2020 19:45:39 +0200 Message-Id: <20201023174546.504028-8-paul.kocialkowski@bootlin.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> References: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201023_134628_692024_82D5D7FA X-CRM114-Status: GOOD ( 14.55 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hans Verkuil , Philipp Zabel , Thomas Petazzoni , Greg Kroah-Hartman , Helen Koike , Vinod Koul , Maxime Ripard , Kishon Vijay Abraham I , Paul Kocialkowski , Chen-Yu Tsai , Rob Herring , Hans Verkuil , Yong Deng , Sakari Ailus , Mauro Carvalho Chehab , kevin.lhopital@hotmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This introduces YAML bindings documentation for the A31 MIPI CSI-2 controller. Signed-off-by: Paul Kocialkowski --- .../media/allwinner,sun6i-a31-mipi-csi2.yaml | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/allwinner,sun6i-a31-mipi-csi2.yaml diff --git a/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-mipi-csi2.yaml b/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-mipi-csi2.yaml new file mode 100644 index 000000000000..9adc0bc27033 --- /dev/null +++ b/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-mipi-csi2.yaml @@ -0,0 +1,168 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/allwinner,sun6i-a31-mipi-csi2.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A31 MIPI CSI-2 Device Tree Bindings + +maintainers: + - Paul Kocialkowski + +properties: + compatible: + oneOf: + - const: allwinner,sun6i-a31-mipi-csi2 + - items: + - const: allwinner,sun8i-v3s-mipi-csi2 + - const: allwinner,sun6i-a31-mipi-csi2 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Bus Clock + - description: Module Clock + + clock-names: + items: + - const: bus + - const: mod + + phys: + items: + - description: MIPI D-PHY + + phy-names: + items: + - const: dphy + + resets: + maxItems: 1 + + # See ./video-interfaces.txt for details + ports: + type: object + + properties: + port@0: + type: object + description: Input port, connect to a MIPI CSI-2 sensor + + properties: + reg: + const: 0 + + endpoint: + type: object + + properties: + remote-endpoint: true + + bus-type: + const: 4 + + clock-lanes: + maxItems: 1 + + data-lanes: + minItems: 1 + maxItems: 4 + + required: + - bus-type + - data-lanes + - remote-endpoint + + additionalProperties: false + + required: + - endpoint + + additionalProperties: false + + port@1: + type: object + description: Output port, connect to a CSI controller + + properties: + reg: + const: 1 + + endpoint: + type: object + + properties: + remote-endpoint: true + + bus-type: + const: 4 + + additionalProperties: false + + required: + - endpoint + + additionalProperties: false + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - resets + +additionalProperties: false + +examples: + - | + #include + #include + #include + + mipi_csi2: mipi-csi2@1cb1000 { + compatible = "allwinner,sun8i-v3s-mipi-csi2", + "allwinner,sun6i-a31-mipi-csi2"; + reg = <0x01cb1000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_BUS_CSI>, + <&ccu CLK_CSI1_SCLK>; + clock-names = "bus", "mod"; + resets = <&ccu RST_BUS_CSI>; + + phys = <&dphy>; + phy-names = "dphy"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + mipi_csi2_in: port@0 { + reg = <0>; + + mipi_csi2_in_ov5648: endpoint { + bus-type = <4>; /* MIPI CSI-2 D-PHY */ + clock-lanes = <0>; + data-lanes = <1 2 3 4>; + + remote-endpoint = <&ov5648_out_mipi_csi2>; + }; + }; + + mipi_csi2_out: port@1 { + reg = <1>; + + mipi_csi2_out_csi0: endpoint { + bus-type = <4>; /* MIPI CSI-2 D-PHY */ + remote-endpoint = <&csi0_in_mipi_csi2>; + }; + }; + }; + }; + +... From patchwork Fri Oct 23 17:45:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Kocialkowski X-Patchwork-Id: 11854303 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D362AC4363A for ; Fri, 23 Oct 2020 17:50:13 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 44EF721582 for ; Fri, 23 Oct 2020 17:50:13 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="18Fj/aUY" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 44EF721582 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=mLJTv9yKlTt7XAzAT+FFaDEYJ7qlJO5Vy+oG9sMSmGg=; b=18Fj/aUY/HdPW9ce8KREiW/s5 UchLN8T8ZNe7uWO5bFVGP/Fu36QiwRKB4MFInbc3O85+JuiGmNHPFt0/JRectDPO6wjCGpH4bp8Qs bipab1R6MNPOEuOoh8EVbJVbyEdBJ8KYrxwJn05WVTyVqeD8x7/wEUz0VStLTbSBQZcxXmkgkP6Kd paQkxl4vmtGZAwv1AiDNaWLYx9TETVbUwiBTXOGRQwO0KhN0Y45LBLjv3rp7XsyVDZRY+fghrizjN sJOLIEZJqWrLmTnrGR2mMD182MiQuQBI4llcUxTUy+wl/As1m15PBkMuKDkkKZVav0Y0Ju06HsLja oCod67nDA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW1AZ-0001Pi-9a; Fri, 23 Oct 2020 17:48:03 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW193-0000pD-Fs for linux-arm-kernel@lists.infradead.org; Fri, 23 Oct 2020 17:46:36 +0000 X-Originating-IP: 93.29.109.196 Received: from localhost.localdomain (196.109.29.93.rev.sfr.net [93.29.109.196]) (Authenticated sender: paul.kocialkowski@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id CA0391BF20E; Fri, 23 Oct 2020 17:46:26 +0000 (UTC) From: Paul Kocialkowski To: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linux-sunxi@googlegroups.com Subject: [PATCH 08/14] media: sunxi: Add support for the A31 MIPI CSI-2 controller Date: Fri, 23 Oct 2020 19:45:40 +0200 Message-Id: <20201023174546.504028-9-paul.kocialkowski@bootlin.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> References: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201023_134629_818369_51B258EB X-CRM114-Status: GOOD ( 29.81 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hans Verkuil , Philipp Zabel , Thomas Petazzoni , Greg Kroah-Hartman , Helen Koike , Vinod Koul , Maxime Ripard , Kishon Vijay Abraham I , Paul Kocialkowski , Chen-Yu Tsai , Rob Herring , Hans Verkuil , Yong Deng , Sakari Ailus , Mauro Carvalho Chehab , kevin.lhopital@hotmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The A31 MIPI CSI-2 controller is a dedicated MIPI CSI-2 controller found on Allwinner SoCs such as the A31 and V3/V3s. It is a standalone block, connected to the CSI controller on one side and to the MIPI D-PHY block on the other. It has a dedicated address space, interrupt line and clock. Currently, the MIPI CSI-2 controller is hard-tied to a specific CSI controller (CSI0) but newer SoCs (such as the V5) may allow switching MIPI CSI-2 controllers between CSI controllers. It is represented as a V4L2 subdev to the CSI controller and takes a MIPI CSI-2 sensor as its own subdev, all using the fwnode graph and media controller API. Signed-off-by: Paul Kocialkowski --- drivers/media/platform/sunxi/Kconfig | 1 + drivers/media/platform/sunxi/Makefile | 1 + .../platform/sunxi/sun6i-mipi-csi2/Kconfig | 11 + .../platform/sunxi/sun6i-mipi-csi2/Makefile | 4 + .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c | 635 ++++++++++++++++++ .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h | 116 ++++ 6 files changed, 768 insertions(+) create mode 100644 drivers/media/platform/sunxi/sun6i-mipi-csi2/Kconfig create mode 100644 drivers/media/platform/sunxi/sun6i-mipi-csi2/Makefile create mode 100644 drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c create mode 100644 drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h diff --git a/drivers/media/platform/sunxi/Kconfig b/drivers/media/platform/sunxi/Kconfig index 7151cc249afa..9684e07454ad 100644 --- a/drivers/media/platform/sunxi/Kconfig +++ b/drivers/media/platform/sunxi/Kconfig @@ -2,3 +2,4 @@ source "drivers/media/platform/sunxi/sun4i-csi/Kconfig" source "drivers/media/platform/sunxi/sun6i-csi/Kconfig" +source "drivers/media/platform/sunxi/sun6i-mipi-csi2/Kconfig" diff --git a/drivers/media/platform/sunxi/Makefile b/drivers/media/platform/sunxi/Makefile index fc537c9f5ca9..887a7cae8fca 100644 --- a/drivers/media/platform/sunxi/Makefile +++ b/drivers/media/platform/sunxi/Makefile @@ -2,5 +2,6 @@ obj-y += sun4i-csi/ obj-y += sun6i-csi/ +obj-y += sun6i-mipi-csi2/ obj-y += sun8i-di/ obj-y += sun8i-rotate/ diff --git a/drivers/media/platform/sunxi/sun6i-mipi-csi2/Kconfig b/drivers/media/platform/sunxi/sun6i-mipi-csi2/Kconfig new file mode 100644 index 000000000000..7033bda483b4 --- /dev/null +++ b/drivers/media/platform/sunxi/sun6i-mipi-csi2/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +config VIDEO_SUN6I_MIPI_CSI2 + tristate "Allwinner A31 MIPI CSI-2 Controller Driver" + depends on VIDEO_V4L2 && COMMON_CLK + depends on ARCH_SUNXI || COMPILE_TEST + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + select REGMAP_MMIO + select V4L2_FWNODE + help + Support for the Allwinner A31 MIPI CSI-2 Controller. diff --git a/drivers/media/platform/sunxi/sun6i-mipi-csi2/Makefile b/drivers/media/platform/sunxi/sun6i-mipi-csi2/Makefile new file mode 100644 index 000000000000..14e4e03818b5 --- /dev/null +++ b/drivers/media/platform/sunxi/sun6i-mipi-csi2/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only +sun6i-mipi-csi2-y += sun6i_mipi_csi2.o + +obj-$(CONFIG_VIDEO_SUN6I_MIPI_CSI2) += sun6i-mipi-csi2.o diff --git a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c new file mode 100644 index 000000000000..ce89c35f5b86 --- /dev/null +++ b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c @@ -0,0 +1,635 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020 Bootlin + * Author: Paul Kocialkowski + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sun6i_mipi_csi2.h" + +#define MODULE_NAME "sun6i-mipi-csi2" + +/* Core */ + +static irqreturn_t sun6i_mipi_csi2_isr(int irq, void *dev_id) +{ + struct sun6i_mipi_csi2_dev *cdev = (struct sun6i_mipi_csi2_dev *)dev_id; + struct regmap *regmap = cdev->regmap; + u32 pending; + + WARN_ONCE(1, MODULE_NAME + ": Unsolicited interrupt, an error likely occurred!\n"); + + regmap_read(regmap, SUN6I_MIPI_CSI2_CH_INT_PD_REG, &pending); + regmap_write(regmap, SUN6I_MIPI_CSI2_CH_INT_PD_REG, pending); + + /* + * The interrupt can be used to catch transmission errors. + * However, we currently lack plumbing for reporting that to the + * A31 CSI controller driver. + */ + + return IRQ_HANDLED; +} + +static int sun6i_mipi_csi2_s_power(struct v4l2_subdev *subdev, int on) +{ + struct sun6i_mipi_csi2_video *video = + sun6i_mipi_csi2_subdev_video(subdev); + struct sun6i_mipi_csi2_dev *cdev = sun6i_mipi_csi2_video_dev(video); + int ret; + + if (!on) { + clk_disable_unprepare(cdev->clk_mod); + reset_control_assert(cdev->reset); + + return 0; + } + + ret = clk_prepare_enable(cdev->clk_mod); + if (ret) { + dev_err(cdev->dev, "failed to enable module clock\n"); + return ret; + } + + ret = reset_control_deassert(cdev->reset); + if (ret) { + dev_err(cdev->dev, "failed to deassert reset\n"); + goto error_clk; + } + + return 0; + +error_clk: + clk_disable_unprepare(cdev->clk_mod); + + return ret; +} + +static const struct v4l2_subdev_core_ops sun6i_mipi_csi2_subdev_core_ops = { + .s_power = sun6i_mipi_csi2_s_power, +}; + +/* Video */ + +static int sun6i_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on) +{ + struct sun6i_mipi_csi2_video *video = + sun6i_mipi_csi2_subdev_video(subdev); + struct sun6i_mipi_csi2_dev *cdev = sun6i_mipi_csi2_video_dev(video); + struct v4l2_subdev *remote_subdev = video->remote_subdev; + struct v4l2_fwnode_bus_mipi_csi2 *bus_mipi_csi2 = + &video->endpoint.bus.mipi_csi2; + union phy_configure_opts dphy_opts = { 0 }; + struct phy_configure_opts_mipi_dphy *dphy_cfg = &dphy_opts.mipi_dphy; + struct regmap *regmap = cdev->regmap; + struct v4l2_ctrl *ctrl; + unsigned int lanes_count; + unsigned int bpp; + unsigned long pixel_rate; + u8 data_type = 0; + u32 version = 0; + /* Initialize to 0 to use both in disable label (ret != 0) and off. */ + int ret = 0; + + if (!remote_subdev) + return -ENODEV; + + if (!on) { + v4l2_subdev_call(remote_subdev, video, s_stream, 0); + +disable: + regmap_update_bits(regmap, SUN6I_MIPI_CSI2_CTL_REG, + SUN6I_MIPI_CSI2_CTL_EN, 0); + + phy_power_off(cdev->dphy); + + return ret; + } + + switch (video->mbus_code) { + case MEDIA_BUS_FMT_SBGGR8_1X8: + case MEDIA_BUS_FMT_SGBRG8_1X8: + case MEDIA_BUS_FMT_SGRBG8_1X8: + case MEDIA_BUS_FMT_SRGGB8_1X8: + data_type = MIPI_CSI2_DATA_TYPE_RAW8; + bpp = 8; + break; + case MEDIA_BUS_FMT_SBGGR10_1X10: + case MEDIA_BUS_FMT_SGBRG10_1X10: + case MEDIA_BUS_FMT_SGRBG10_1X10: + case MEDIA_BUS_FMT_SRGGB10_1X10: + data_type = MIPI_CSI2_DATA_TYPE_RAW10; + bpp = 10; + break; + default: + return -EINVAL; + } + + /* Sensor pixel rate */ + + ctrl = v4l2_ctrl_find(remote_subdev->ctrl_handler, V4L2_CID_PIXEL_RATE); + if (!ctrl) { + dev_err(cdev->dev, + "%s: no MIPI CSI-2 pixel rate from the sensor\n", + __func__); + return -ENODEV; + } + + pixel_rate = (unsigned long)v4l2_ctrl_g_ctrl_int64(ctrl); + if (!pixel_rate) { + dev_err(cdev->dev, + "%s: zero MIPI CSI-2 pixel rate from the sensor\n", + __func__); + return -ENODEV; + } + + /* D-PHY configuration */ + + lanes_count = bus_mipi_csi2->num_data_lanes; + phy_mipi_dphy_get_default_config(pixel_rate, bpp, lanes_count, + dphy_cfg); + + + /* + * Note that our hardware is using DDR, which is not taken in account by + * phy_mipi_dphy_get_default_config when calculating hs_clk_rate from + * the pixel rate, lanes count and bpp. + * + * The resulting clock rate is basically the symbol rate over the whole + * link. The actual clock rate is calculated with division by two since + * DDR samples both on rising and falling edges. + */ + + dev_dbg(cdev->dev, "A31 MIPI CSI-2 config:\n"); + dev_dbg(cdev->dev, "%ld pixels/s, %u bits/pixel, %lu Hz clock\n", + pixel_rate, bpp, dphy_cfg->hs_clk_rate / 2); + + ret = 0; + ret |= phy_reset(cdev->dphy); + ret |= phy_set_mode_ext(cdev->dphy, PHY_MODE_MIPI_DPHY, + PHY_MIPI_DPHY_SUBMODE_RX); + ret |= phy_configure(cdev->dphy, &dphy_opts); + + if (ret) { + dev_err(cdev->dev, "failed to setup MIPI D-PHY\n"); + return ret; + } + + ret = phy_power_on(cdev->dphy); + if (ret) { + dev_err(cdev->dev, "failed to power on MIPI D-PHY\n"); + return ret; + } + + /* MIPI CSI-2 controller setup */ + + /* + * The enable flow in the Allwinner BSP is a bit different: the enable + * and reset bits are set together before starting the CSI controller. + * + * In mainline we enable the CSI controller first (due to subdev logic). + * One reliable way to make this work is to deassert reset, configure + * registers and enable the controller when everything's ready. + * + * However, reading the version appears necessary for it to work + * reliably. Replacing it with a delay doesn't do the trick. + */ + regmap_write(regmap, SUN6I_MIPI_CSI2_CTL_REG, + SUN6I_MIPI_CSI2_CTL_RESET_N | + SUN6I_MIPI_CSI2_CTL_VERSION_EN | + SUN6I_MIPI_CSI2_CTL_UNPK_EN); + + regmap_read(regmap, SUN6I_MIPI_CSI2_VERSION_REG, &version); + + regmap_update_bits(regmap, SUN6I_MIPI_CSI2_CTL_REG, + SUN6I_MIPI_CSI2_CTL_VERSION_EN, 0); + + dev_dbg(cdev->dev, "A31 MIPI CSI-2 version: %04x\n", version); + + regmap_write(regmap, SUN6I_MIPI_CSI2_CFG_REG, + SUN6I_MIPI_CSI2_CFG_CHANNEL_MODE(1) | + SUN6I_MIPI_CSI2_CFG_LANE_COUNT(lanes_count)); + + regmap_write(regmap, SUN6I_MIPI_CSI2_VCDT_RX_REG, + SUN6I_MIPI_CSI2_VCDT_RX_CH_VC(3, 3) | + SUN6I_MIPI_CSI2_VCDT_RX_CH_VC(2, 2) | + SUN6I_MIPI_CSI2_VCDT_RX_CH_VC(1, 1) | + SUN6I_MIPI_CSI2_VCDT_RX_CH_VC(0, 0) | + SUN6I_MIPI_CSI2_VCDT_RX_CH_DT(0, data_type)); + + regmap_update_bits(regmap, SUN6I_MIPI_CSI2_CTL_REG, + SUN6I_MIPI_CSI2_CTL_EN, SUN6I_MIPI_CSI2_CTL_EN); + + ret = v4l2_subdev_call(remote_subdev, video, s_stream, 1); + if (ret) + goto disable; + + return 0; +} + +static const struct v4l2_subdev_video_ops sun6i_mipi_csi2_subdev_video_ops = { + .s_stream = sun6i_mipi_csi2_s_stream, +}; + +/* Pad */ + +static int sun6i_mipi_csi2_enum_mbus_code(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *config, + struct v4l2_subdev_mbus_code_enum *code_enum) +{ + struct sun6i_mipi_csi2_video *video = + sun6i_mipi_csi2_subdev_video(subdev); + + if (!video->remote_subdev) + return -ENODEV; + + /* Forward to the sensor. */ + code_enum->pad = video->remote_pad_index; + + return v4l2_subdev_call(video->remote_subdev, pad, enum_mbus_code, + config, code_enum); +} + +static int sun6i_mipi_csi2_get_fmt(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *config, + struct v4l2_subdev_format *format) +{ + struct sun6i_mipi_csi2_video *video = + sun6i_mipi_csi2_subdev_video(subdev); + + if (!video->remote_subdev) + return -ENODEV; + + /* Forward to the sensor. */ + format->pad = video->remote_pad_index; + + return v4l2_subdev_call(video->remote_subdev, pad, get_fmt, config, + format); +} + +static int sun6i_mipi_csi2_set_fmt(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *config, + struct v4l2_subdev_format *format) +{ + struct sun6i_mipi_csi2_video *video = + sun6i_mipi_csi2_subdev_video(subdev); + + if (!video->remote_subdev) + return -ENODEV; + + /* Forward to the sensor. */ + format->pad = video->remote_pad_index; + + return v4l2_subdev_call(video->remote_subdev, pad, set_fmt, config, + format); +} + +static int sun6i_mipi_csi2_enum_frame_size(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *config, + struct v4l2_subdev_frame_size_enum *size_enum) +{ + struct sun6i_mipi_csi2_video *video = + sun6i_mipi_csi2_subdev_video(subdev); + + if (!video->remote_subdev) + return -ENODEV; + + /* Forward to the sensor. */ + size_enum->pad = video->remote_pad_index; + + return v4l2_subdev_call(video->remote_subdev, pad, enum_frame_size, + config, size_enum); +} + +static int sun6i_mipi_csi2_enum_frame_interval(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *config, + struct v4l2_subdev_frame_interval_enum *interval_enum) +{ + struct sun6i_mipi_csi2_video *video = + sun6i_mipi_csi2_subdev_video(subdev); + + if (!video->remote_subdev) + return -ENODEV; + + /* Forward to the sensor. */ + interval_enum->pad = video->remote_pad_index; + + return v4l2_subdev_call(video->remote_subdev, pad, enum_frame_interval, + config, interval_enum); +} + +static const struct v4l2_subdev_pad_ops sun6i_mipi_csi2_subdev_pad_ops = { + .enum_mbus_code = sun6i_mipi_csi2_enum_mbus_code, + .get_fmt = sun6i_mipi_csi2_get_fmt, + .set_fmt = sun6i_mipi_csi2_set_fmt, + .enum_frame_size = sun6i_mipi_csi2_enum_frame_size, + .enum_frame_interval = sun6i_mipi_csi2_enum_frame_interval, +}; + +/* Subdev */ + +static const struct v4l2_subdev_ops sun6i_mipi_csi2_subdev_ops = { + .core = &sun6i_mipi_csi2_subdev_core_ops, + .video = &sun6i_mipi_csi2_subdev_video_ops, + .pad = &sun6i_mipi_csi2_subdev_pad_ops, +}; + +/* Notifier */ + +static int sun6i_mipi_csi2_notifier_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *remote_subdev, + struct v4l2_async_subdev *remote_subdev_async) +{ + struct v4l2_subdev *subdev = notifier->sd; + struct sun6i_mipi_csi2_video *video = + sun6i_mipi_csi2_subdev_video(subdev); + struct sun6i_mipi_csi2_dev *cdev = sun6i_mipi_csi2_video_dev(video); + int source_pad; + int ret; + + source_pad = media_entity_get_fwnode_pad(&remote_subdev->entity, + remote_subdev->fwnode, + MEDIA_PAD_FL_SOURCE); + if (source_pad < 0) + return source_pad; + + ret = media_create_pad_link(&remote_subdev->entity, source_pad, + &subdev->entity, 0, + MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); + if (ret) { + dev_err(cdev->dev, "failed to create %s:%u -> %s:%u link\n", + remote_subdev->entity.name, source_pad, + subdev->entity.name, 0); + return ret; + } + + video->remote_subdev = remote_subdev; + video->remote_pad_index = source_pad; + + return 0; +} + +static const struct v4l2_async_notifier_operations sun6i_mipi_csi2_notifier_ops = { + .bound = sun6i_mipi_csi2_notifier_bound, +}; + +/* Media Entity */ + +static int sun6i_mipi_csi2_link_validate(struct media_link *link) +{ + struct v4l2_subdev *subdev = + container_of(link->sink->entity, struct v4l2_subdev, entity); + struct sun6i_mipi_csi2_video *video = + sun6i_mipi_csi2_subdev_video(subdev); + struct v4l2_subdev *remote_subdev; + struct v4l2_subdev_format format = { 0 }; + int ret; + + if (!is_media_entity_v4l2_subdev(link->source->entity)) + return -EINVAL; + + remote_subdev = media_entity_to_v4l2_subdev(link->source->entity); + + format.which = V4L2_SUBDEV_FORMAT_ACTIVE; + format.pad = link->source->index; + + ret = v4l2_subdev_call(remote_subdev, pad, get_fmt, NULL, &format); + if (ret) + return ret; + + video->mbus_code = format.format.code; + + return 0; +} + +static const struct media_entity_operations sun6i_mipi_csi2_entity_ops = { + .link_validate = sun6i_mipi_csi2_link_validate, +}; + +/* Base Driver */ + +static int sun6i_mipi_csi2_v4l2_setup(struct sun6i_mipi_csi2_dev *cdev) +{ + struct sun6i_mipi_csi2_video *video = &cdev->video; + struct v4l2_subdev *subdev = &video->subdev; + struct v4l2_async_notifier *notifier = &video->notifier; + struct fwnode_handle *handle; + struct v4l2_fwnode_endpoint *endpoint; + int ret; + + /* Subdev */ + + v4l2_subdev_init(subdev, &sun6i_mipi_csi2_subdev_ops); + subdev->dev = cdev->dev; + strscpy(subdev->name, MODULE_NAME, sizeof(subdev->name)); + v4l2_set_subdevdata(subdev, cdev); + + /* Entity */ + + subdev->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; + subdev->entity.ops = &sun6i_mipi_csi2_entity_ops; + + /* Pads */ + + video->pads[0].flags = MEDIA_PAD_FL_SINK; + video->pads[1].flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(&subdev->entity, 2, video->pads); + if (ret) + return ret; + + /* Endpoint */ + + handle = fwnode_graph_get_endpoint_by_id(dev_fwnode(cdev->dev), 0, 0, + FWNODE_GRAPH_ENDPOINT_NEXT); + if (!handle) + goto error_media_entity; + + endpoint = &video->endpoint; + endpoint->bus_type = V4L2_MBUS_CSI2_DPHY; + + ret = v4l2_fwnode_endpoint_parse(handle, endpoint); + fwnode_handle_put(handle); + if (ret) + goto error_media_entity; + + /* Notifier */ + + v4l2_async_notifier_init(notifier); + + ret = v4l2_async_notifier_add_fwnode_remote_subdev(notifier, handle, + &video->subdev_async); + if (ret) + goto error_media_entity; + + video->notifier.ops = &sun6i_mipi_csi2_notifier_ops; + + ret = v4l2_async_subdev_notifier_register(subdev, notifier); + if (ret < 0) + goto error_notifier; + + /* Subdev */ + + ret = v4l2_async_register_subdev(subdev); + if (ret < 0) + goto error_notifier_registered; + + return 0; + +error_notifier_registered: + v4l2_async_notifier_unregister(notifier); +error_notifier: + v4l2_async_notifier_cleanup(notifier); +error_media_entity: + media_entity_cleanup(&subdev->entity); + + return ret; +} + +static int sun6i_mipi_csi2_v4l2_teardown(struct sun6i_mipi_csi2_dev *cdev) +{ + struct sun6i_mipi_csi2_video *video = &cdev->video; + struct v4l2_subdev *subdev = &video->subdev; + struct v4l2_async_notifier *notifier = &video->notifier; + + v4l2_async_unregister_subdev(subdev); + v4l2_async_notifier_unregister(notifier); + v4l2_async_notifier_cleanup(notifier); + media_entity_cleanup(&subdev->entity); + v4l2_device_unregister_subdev(subdev); + + return 0; +} + +static const struct regmap_config sun6i_mipi_csi2_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x400, +}; + +static int sun6i_mipi_csi2_resource_request(struct sun6i_mipi_csi2_dev *cdev, + struct platform_device *pdev) +{ + struct resource *res; + void __iomem *io_base; + int irq; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + io_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(io_base)) + return PTR_ERR(io_base); + + cdev->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "bus", io_base, + &sun6i_mipi_csi2_regmap_config); + if (IS_ERR(cdev->regmap)) { + dev_err(&pdev->dev, "failed to init register map\n"); + return PTR_ERR(cdev->regmap); + } + + cdev->clk_mod = devm_clk_get(&pdev->dev, "mod"); + if (IS_ERR(cdev->clk_mod)) { + dev_err(&pdev->dev, "failed to acquire csi clock\n"); + return PTR_ERR(cdev->clk_mod); + } + + cdev->reset = devm_reset_control_get_shared(&pdev->dev, NULL); + if (IS_ERR(cdev->reset)) { + dev_err(&pdev->dev, "failed to get reset controller\n"); + return PTR_ERR(cdev->reset); + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return -ENXIO; + + ret = devm_request_irq(&pdev->dev, irq, sun6i_mipi_csi2_isr, 0, + MODULE_NAME, cdev); + if (ret) { + dev_err(&pdev->dev, "failed to request MIPI CSI-2 IRQ\n"); + return ret; + } + + cdev->dphy = devm_phy_get(&pdev->dev, "dphy"); + if (IS_ERR(cdev->dphy)) { + dev_err(&pdev->dev, "failed to get the MIPI D-PHY\n"); + return PTR_ERR(cdev->dphy); + } + + ret = phy_init(cdev->dphy); + if (ret) { + dev_err(&pdev->dev, "failed to initialize the MIPI D-PHY\n"); + return ret; + } + + return 0; +} + +static int sun6i_mipi_csi2_probe(struct platform_device *pdev) +{ + struct sun6i_mipi_csi2_dev *cdev; + int ret; + + cdev = devm_kzalloc(&pdev->dev, sizeof(*cdev), GFP_KERNEL); + if (!cdev) + return -ENOMEM; + + cdev->dev = &pdev->dev; + + ret = sun6i_mipi_csi2_resource_request(cdev, pdev); + if (ret) + return ret; + + platform_set_drvdata(pdev, cdev); + + ret = sun6i_mipi_csi2_v4l2_setup(cdev); + if (ret) + return ret; + + return 0; +} + +static int sun6i_mipi_csi2_remove(struct platform_device *pdev) +{ + struct sun6i_mipi_csi2_dev *cdev = platform_get_drvdata(pdev); + + phy_exit(cdev->dphy); + + return sun6i_mipi_csi2_v4l2_teardown(cdev); +} + +static const struct of_device_id sun6i_mipi_csi2_of_match[] = { + { .compatible = "allwinner,sun6i-a31-mipi-csi2" }, + { .compatible = "allwinner,sun8i-v3s-mipi-csi2", }, + {}, +}; +MODULE_DEVICE_TABLE(of, sun6i_mipi_csi2_of_match); + +static struct platform_driver sun6i_mipi_csi2_platform_driver = { + .probe = sun6i_mipi_csi2_probe, + .remove = sun6i_mipi_csi2_remove, + .driver = { + .name = MODULE_NAME, + .of_match_table = of_match_ptr(sun6i_mipi_csi2_of_match), + }, +}; +module_platform_driver(sun6i_mipi_csi2_platform_driver); + +MODULE_DESCRIPTION("Allwinner A31 MIPI CSI-2 Controller Driver"); +MODULE_AUTHOR("Paul Kocialkowski "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h new file mode 100644 index 000000000000..f3cce99bfd44 --- /dev/null +++ b/drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2020 Bootlin + * Author: Paul Kocialkowski + */ + +#ifndef __SUN6I_MIPI_CSI2_H__ +#define __SUN6I_MIPI_CSI2_H__ + +#include +#include +#include +#include +#include + +#define SUN6I_MIPI_CSI2_CTL_REG 0x0 +#define SUN6I_MIPI_CSI2_CTL_RESET_N BIT(31) +#define SUN6I_MIPI_CSI2_CTL_VERSION_EN BIT(30) +#define SUN6I_MIPI_CSI2_CTL_UNPK_EN BIT(1) +#define SUN6I_MIPI_CSI2_CTL_EN BIT(0) +#define SUN6I_MIPI_CSI2_CFG_REG 0x4 +#define SUN6I_MIPI_CSI2_CFG_CHANNEL_MODE(v) ((((v) - 1) << 8) & \ + GENMASK(9, 8)) +#define SUN6I_MIPI_CSI2_CFG_LANE_COUNT(v) (((v) - 1) & GENMASK(1, 0)) +#define SUN6I_MIPI_CSI2_VCDT_RX_REG 0x8 +#define SUN6I_MIPI_CSI2_VCDT_RX_CH_VC(ch, vc) (((vc) & GENMASK(1, 0)) << \ + ((ch) * 8 + 6)) +#define SUN6I_MIPI_CSI2_VCDT_RX_CH_DT(ch, t) (((t) & GENMASK(5, 0)) << \ + ((ch) * 8)) +#define SUN6I_MIPI_CSI2_RX_PKT_NUM_REG 0xc + +#define SUN6I_MIPI_CSI2_VERSION_REG 0x3c + +#define SUN6I_MIPI_CSI2_CH_BASE 0x1000 +#define SUN6I_MIPI_CSI2_CH_OFFSET 0x100 + +#define SUN6I_MIPI_CSI2_CH_CFG_REG 0x40 +#define SUN6I_MIPI_CSI2_CH_INT_EN_REG 0x50 +#define SUN6I_MIPI_CSI2_CH_INT_EN_EOT_ERR BIT(29) +#define SUN6I_MIPI_CSI2_CH_INT_EN_CHKSUM_ERR BIT(28) +#define SUN6I_MIPI_CSI2_CH_INT_EN_ECC_WRN BIT(27) +#define SUN6I_MIPI_CSI2_CH_INT_EN_ECC_ERR BIT(26) +#define SUN6I_MIPI_CSI2_CH_INT_EN_LINE_SYNC_ERR BIT(25) +#define SUN6I_MIPI_CSI2_CH_INT_EN_FRAME_SYNC_ERR BIT(24) +#define SUN6I_MIPI_CSI2_CH_INT_EN_EMB_DATA BIT(18) +#define SUN6I_MIPI_CSI2_CH_INT_EN_PF BIT(17) +#define SUN6I_MIPI_CSI2_CH_INT_EN_PH_UPDATE BIT(16) +#define SUN6I_MIPI_CSI2_CH_INT_EN_LINE_START_SYNC BIT(11) +#define SUN6I_MIPI_CSI2_CH_INT_EN_LINE_END_SYNC BIT(10) +#define SUN6I_MIPI_CSI2_CH_INT_EN_FRAME_START_SYNC BIT(9) +#define SUN6I_MIPI_CSI2_CH_INT_EN_FRAME_END_SYNC BIT(8) +#define SUN6I_MIPI_CSI2_CH_INT_EN_FIFO_OVER BIT(0) + +#define SUN6I_MIPI_CSI2_CH_INT_PD_REG 0x58 +#define SUN6I_MIPI_CSI2_CH_INT_PD_EOT_ERR BIT(29) +#define SUN6I_MIPI_CSI2_CH_INT_PD_CHKSUM_ERR BIT(28) +#define SUN6I_MIPI_CSI2_CH_INT_PD_ECC_WRN BIT(27) +#define SUN6I_MIPI_CSI2_CH_INT_PD_ECC_ERR BIT(26) +#define SUN6I_MIPI_CSI2_CH_INT_PD_LINE_SYNC_ERR BIT(25) +#define SUN6I_MIPI_CSI2_CH_INT_PD_FRAME_SYNC_ERR BIT(24) +#define SUN6I_MIPI_CSI2_CH_INT_PD_EMB_DATA BIT(18) +#define SUN6I_MIPI_CSI2_CH_INT_PD_PF BIT(17) +#define SUN6I_MIPI_CSI2_CH_INT_PD_PH_UPDATE BIT(16) +#define SUN6I_MIPI_CSI2_CH_INT_PD_LINE_START_SYNC BIT(11) +#define SUN6I_MIPI_CSI2_CH_INT_PD_LINE_END_SYNC BIT(10) +#define SUN6I_MIPI_CSI2_CH_INT_PD_FRAME_START_SYNC BIT(9) +#define SUN6I_MIPI_CSI2_CH_INT_PD_FRAME_END_SYNC BIT(8) +#define SUN6I_MIPI_CSI2_CH_INT_PD_FIFO_OVER BIT(0) + +#define SUN6I_MIPI_CSI2_CH_DT_TRIGGER_REG 0x60 +#define SUN6I_MIPI_CSI2_CH_CUR_PH_REG 0x70 +#define SUN6I_MIPI_CSI2_CH_ECC_REG 0x74 +#define SUN6I_MIPI_CSI2_CH_CKS_REG 0x78 +#define SUN6I_MIPI_CSI2_CH_FRAME_NUM_REG 0x7c +#define SUN6I_MIPI_CSI2_CH_LINE_NUM_REG 0x80 + +#define SUN6I_MIPI_CSI2_CH_REG(reg, ch) \ + (SUN6I_MIPI_CSI2_CH_BASE + SUN6I_MIPI_CSI2_CH_OFFSET * (ch) + (reg)) + +enum mipi_csi2_data_type { + MIPI_CSI2_DATA_TYPE_RAW8 = 0x2a, + MIPI_CSI2_DATA_TYPE_RAW10 = 0x2b, + MIPI_CSI2_DATA_TYPE_RAW12 = 0x2c, +}; + +struct sun6i_mipi_csi2_video { + struct v4l2_fwnode_endpoint endpoint; + struct v4l2_subdev subdev; + struct media_pad pads[2]; + + struct v4l2_async_subdev subdev_async; + struct v4l2_async_notifier notifier; + + struct v4l2_subdev *remote_subdev; + u32 remote_pad_index; + u32 mbus_code; +}; + +struct sun6i_mipi_csi2_dev { + struct device *dev; + + struct regmap *regmap; + struct clk *clk_mod; + struct reset_control *reset; + struct phy *dphy; + + struct sun6i_mipi_csi2_video video; +}; + +#define sun6i_mipi_csi2_subdev_video(subdev) \ + container_of(subdev, struct sun6i_mipi_csi2_video, subdev) + +#define sun6i_mipi_csi2_video_dev(video) \ + container_of(video, struct sun6i_mipi_csi2_dev, video) + +#endif /* __SUN6I_MIPI_CSI2_H__ */ From patchwork Fri Oct 23 17:45:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Kocialkowski X-Patchwork-Id: 11854293 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EACC1C4363A for ; Fri, 23 Oct 2020 17:49:49 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0D4FB21582 for ; Fri, 23 Oct 2020 17:49:48 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="ybAnDFkz" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0D4FB21582 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=rQebl+Uj0cRfxz5HdMxkbr5QucEwtVH6Q2XpldPimSg=; b=ybAnDFkzLx1nQpnxLlB53Z/7G 5WyXBQ6mtd/wuJu6WARLu8VmpVNq7fCJTSyCpcSnyputnl0bfiQ23TvWbDvBFnAsW19dZxE87hGz8 g6ClWluUTWao+gUaGQRwIdRFVPBUZytqNIAcxDanWGzgjlykiRou061npMb8yNwl6t2irq5yI1i8A Ew2pOdDQIKjduTFTxg+1mvDO982HxkE44l1mZzBF6VKLyi8D+QX/9A/RqD6IcSmlMM5qKcbLitkq2 N62/m/iFK2eVmsrlKjDJqzNqotBX2gpX1nkPtdHDyyp8JKtjRteXsnQ2U0v3+glHXS6mI7gM+GQo3 ZOZRwapeQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW1AI-0001Es-Kt; Fri, 23 Oct 2020 17:47:46 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW195-0000qL-97 for linux-arm-kernel@lists.infradead.org; Fri, 23 Oct 2020 17:46:32 +0000 X-Originating-IP: 93.29.109.196 Received: from localhost.localdomain (196.109.29.93.rev.sfr.net [93.29.109.196]) (Authenticated sender: paul.kocialkowski@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 97DF71BF204; Fri, 23 Oct 2020 17:46:28 +0000 (UTC) From: Paul Kocialkowski To: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linux-sunxi@googlegroups.com Subject: [PATCH 09/14] ARM: dts: sun8i: v3s: Add CSI0 camera interface node Date: Fri, 23 Oct 2020 19:45:41 +0200 Message-Id: <20201023174546.504028-10-paul.kocialkowski@bootlin.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> References: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201023_134631_460871_63D86313 X-CRM114-Status: GOOD ( 13.15 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hans Verkuil , Philipp Zabel , Thomas Petazzoni , Greg Kroah-Hartman , Helen Koike , Vinod Koul , Maxime Ripard , Kishon Vijay Abraham I , Paul Kocialkowski , Chen-Yu Tsai , Rob Herring , Hans Verkuil , Yong Deng , Sakari Ailus , Mauro Carvalho Chehab , kevin.lhopital@hotmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The V3s has a CSI0 camera controller which seems to be exclusively dedicated to MIPI CSI-2, as it does not seem to have access to a set of parallel input pins. Signed-off-by: Paul Kocialkowski --- arch/arm/boot/dts/sun8i-v3s.dtsi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi index 0c7341676921..07722bc5df11 100644 --- a/arch/arm/boot/dts/sun8i-v3s.dtsi +++ b/arch/arm/boot/dts/sun8i-v3s.dtsi @@ -524,6 +524,18 @@ spi0: spi@1c68000 { #size-cells = <0>; }; + csi0: camera@1cb0000 { + compatible = "allwinner,sun8i-v3s-csi"; + reg = <0x01cb0000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_BUS_CSI>, + <&ccu CLK_CSI1_SCLK>, + <&ccu CLK_DRAM_CSI>; + clock-names = "bus", "mod", "ram"; + resets = <&ccu RST_BUS_CSI>; + status = "disabled"; + }; + csi1: camera@1cb4000 { compatible = "allwinner,sun8i-v3s-csi"; reg = <0x01cb4000 0x3000>; From patchwork Fri Oct 23 17:45:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Kocialkowski X-Patchwork-Id: 11854299 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CF786C4363A for ; Fri, 23 Oct 2020 17:50:01 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 544002192A for ; Fri, 23 Oct 2020 17:50:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="k1G8vQhR" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 544002192A Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=TNp+ykQnxp6HEchD4bMQuhTrEs8clBWkTFnXwLSfdSg=; b=k1G8vQhRF3G0nSxZ4gn4lHH9D PumQGutHBqwF4x6a4vDfSiOoiWJBkEWNFV+YXS5d4mrAb4jsDKY4wb2AD5Dj3BQLAAIa8cno0ND5d PBojz5C0j/t7drhkJY0jVhT9bGBob6deDT2bakhN7k2Lsq27ImcEcPShszuJcLbcBZtygQa7qPouS 5AlNvD+KJCwl2aGj3e4QilV5vdHMmQ3LMV/v/tqWed3mnbtiOZM+AQtUFfCrPcREVo4FdnEz/4ANY XOCaXVvC+9O35C2DrkX/QW8Lir63L9R4S3jBIwfu0XAJ/M85XYhKzq4QhfoPMyL1EMbktdNWgQHlQ 2dCgrZZbQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW1Ae-0001YG-1r; Fri, 23 Oct 2020 17:48:08 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW197-0000rH-F9 for linux-arm-kernel@lists.infradead.org; Fri, 23 Oct 2020 17:46:40 +0000 X-Originating-IP: 93.29.109.196 Received: from localhost.localdomain (196.109.29.93.rev.sfr.net [93.29.109.196]) (Authenticated sender: paul.kocialkowski@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 7F7921BF210; Fri, 23 Oct 2020 17:46:30 +0000 (UTC) From: Paul Kocialkowski To: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linux-sunxi@googlegroups.com Subject: [PATCH 10/14] ARM: dts: sun8i: v3s: Add MIPI D-PHY and MIPI CSI-2 interface nodes Date: Fri, 23 Oct 2020 19:45:42 +0200 Message-Id: <20201023174546.504028-11-paul.kocialkowski@bootlin.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> References: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201023_134633_712188_AAD79313 X-CRM114-Status: GOOD ( 14.00 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hans Verkuil , Philipp Zabel , Thomas Petazzoni , Greg Kroah-Hartman , Helen Koike , Vinod Koul , Maxime Ripard , Kishon Vijay Abraham I , Paul Kocialkowski , Chen-Yu Tsai , Rob Herring , Hans Verkuil , Yong Deng , Sakari Ailus , Mauro Carvalho Chehab , kevin.lhopital@hotmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org MIPI CSI-2 is supported on the V3s with an A31 controller, which seems to be used on all Allwinner chips supporting it, except for the A83T. The controller is connected to CSI0 through fwnode endpoints. The mipi_csi2_in port node is provided to connect MIPI CSI-2 sensors. The D-PHY part is the same that already drives DSI, but used in Rx mode. Signed-off-by: Paul Kocialkowski --- arch/arm/boot/dts/sun8i-v3s.dtsi | 50 ++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi index 07722bc5df11..6e10c10ab283 100644 --- a/arch/arm/boot/dts/sun8i-v3s.dtsi +++ b/arch/arm/boot/dts/sun8i-v3s.dtsi @@ -534,6 +534,13 @@ csi0: camera@1cb0000 { clock-names = "bus", "mod", "ram"; resets = <&ccu RST_BUS_CSI>; status = "disabled"; + + csi0_in: port { + csi0_in_mipi_csi2: endpoint { + bus-type = <4>; /* CSI2_DPHY */ + remote-endpoint = <&mipi_csi2_out_csi0>; + }; + }; }; csi1: camera@1cb4000 { @@ -558,5 +565,48 @@ gic: interrupt-controller@1c81000 { #interrupt-cells = <3>; interrupts = ; }; + + mipi_csi2: mipi-csi2@1cb1000 { + compatible = "allwinner,sun8i-v3s-mipi-csi2", + "allwinner,sun6i-a31-mipi-csi2"; + reg = <0x01cb1000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_BUS_CSI>, + <&ccu CLK_CSI1_SCLK>; + clock-names = "bus", "mod"; + resets = <&ccu RST_BUS_CSI>; + status = "disabled"; + + phys = <&dphy>; + phy-names = "dphy"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + mipi_csi2_in: port@0 { + reg = <0>; + }; + + mipi_csi2_out: port@1 { + reg = <1>; + + mipi_csi2_out_csi0: endpoint { + remote-endpoint = <&csi0_in_mipi_csi2>; + }; + }; + }; + }; + + dphy: d-phy@1cb2000 { + compatible = "allwinner,sun6i-a31-mipi-dphy"; + reg = <0x01cb2000 0x1000>; + clocks = <&ccu CLK_BUS_CSI>, + <&ccu CLK_MIPI_CSI>; + clock-names = "bus", "mod"; + resets = <&ccu RST_BUS_CSI>; + status = "disabled"; + #phy-cells = <0>; + }; }; }; From patchwork Fri Oct 23 17:45:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Kocialkowski X-Patchwork-Id: 11854307 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 96ECBC5517A for ; Fri, 23 Oct 2020 17:50:26 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2B69621582 for ; Fri, 23 Oct 2020 17:50:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="0Vv9H2Fh" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2B69621582 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=Ad1estgFer6ZHM6CL4CxQT0XZ5QVAXFKvjlH4z9ZhLo=; b=0Vv9H2FhQnSKZOVZ01/GG9Skd LUeaq7b31r2sxXDzxByAioCynuHfO3Zo2J5h3j+e3UnlZxzHLk+VRCGMzJL7PEh3u95WKJ/Z3x4DX E3/2qyV6LrHVdwArlII5o1XKURoCmYx0FNcnIgkpQuds+jlUCkPzYyXF8E+aOUkB7yA2+gYc/LJXM rbViZo8Cr1R/Dactl2JnpMI9NJ8QqucpYkI7WypLyQ/oFvqn9Dbd6mDvR7RaMm6FokVX6VZJnGATE 90Zhv6vLbQJgDude8TJ2kGpizBVAbQxi59UiAErjT6fFFsoTe2kmHGhDOSDrZXOD8NgYtC9qkqN1l AoSQtmC3w==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW1Aq-0001c0-7n; Fri, 23 Oct 2020 17:48:20 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW199-0000tB-92 for linux-arm-kernel@lists.infradead.org; Fri, 23 Oct 2020 17:46:42 +0000 X-Originating-IP: 93.29.109.196 Received: from localhost.localdomain (196.109.29.93.rev.sfr.net [93.29.109.196]) (Authenticated sender: paul.kocialkowski@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id A09011BF213; Fri, 23 Oct 2020 17:46:32 +0000 (UTC) From: Paul Kocialkowski To: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linux-sunxi@googlegroups.com Subject: [PATCH 11/14] dt-bindings: media: i2c: Add A83T MIPI CSI-2 bindings documentation Date: Fri, 23 Oct 2020 19:45:43 +0200 Message-Id: <20201023174546.504028-12-paul.kocialkowski@bootlin.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> References: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201023_134635_597401_0183B46F X-CRM114-Status: GOOD ( 14.54 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hans Verkuil , Philipp Zabel , Thomas Petazzoni , Greg Kroah-Hartman , Helen Koike , Vinod Koul , Maxime Ripard , Kishon Vijay Abraham I , Paul Kocialkowski , Chen-Yu Tsai , Rob Herring , Hans Verkuil , Yong Deng , Sakari Ailus , Mauro Carvalho Chehab , kevin.lhopital@hotmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This introduces YAML bindings documentation for the A83T MIPI CSI-2 controller. Signed-off-by: Paul Kocialkowski --- .../media/allwinner,sun8i-a83t-mipi-csi2.yaml | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/allwinner,sun8i-a83t-mipi-csi2.yaml diff --git a/Documentation/devicetree/bindings/media/allwinner,sun8i-a83t-mipi-csi2.yaml b/Documentation/devicetree/bindings/media/allwinner,sun8i-a83t-mipi-csi2.yaml new file mode 100644 index 000000000000..2384ae4e7be0 --- /dev/null +++ b/Documentation/devicetree/bindings/media/allwinner,sun8i-a83t-mipi-csi2.yaml @@ -0,0 +1,158 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/allwinner,sun8i-a83t-mipi-csi2.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A83T MIPI CSI-2 Device Tree Bindings + +maintainers: + - Paul Kocialkowski + +properties: + compatible: + const: allwinner,sun8i-a83t-mipi-csi2 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Bus Clock + - description: Module Clock + - description: MIPI-specific Clock + - description: Misc CSI Clock + + clock-names: + items: + - const: bus + - const: mod + - const: mipi + - const: misc + + resets: + maxItems: 1 + + # See ./video-interfaces.txt for details + ports: + type: object + + properties: + port@0: + type: object + description: Input port, connect to a MIPI CSI-2 sensor + + properties: + reg: + const: 0 + + endpoint: + type: object + + properties: + remote-endpoint: true + + bus-type: + const: 4 + + clock-lanes: + maxItems: 1 + + data-lanes: + minItems: 1 + maxItems: 4 + + required: + - bus-type + - data-lanes + - remote-endpoint + + additionalProperties: false + + required: + - endpoint + + additionalProperties: false + + port@1: + type: object + description: Output port, connect to a CSI controller + + properties: + reg: + const: 1 + + endpoint: + type: object + + properties: + remote-endpoint: true + + bus-type: + const: 4 + + additionalProperties: false + + required: + - endpoint + + additionalProperties: false + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - resets + +additionalProperties: false + +examples: + - | + #include + #include + #include + + mipi_csi2: mipi-csi2@1cb1000 { + compatible = "allwinner,sun8i-a83t-mipi-csi2"; + reg = <0x01cb1000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_BUS_CSI>, + <&ccu CLK_CSI_SCLK>, + <&ccu CLK_MIPI_CSI>, + <&ccu CLK_CSI_MISC>; + clock-names = "bus", "mod", "mipi", "misc"; + resets = <&ccu RST_BUS_CSI>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + mipi_csi2_in: port@0 { + reg = <0>; + + mipi_csi2_in_ov8865: endpoint { + bus-type = <4>; /* MIPI CSI-2 D-PHY */ + clock-lanes = <0>; + data-lanes = <1 2 3 4>; + + remote-endpoint = <&ov8865_out_mipi_csi2>; + }; + }; + + mipi_csi2_out: port@1 { + reg = <1>; + + mipi_csi2_out_csi: endpoint { + bus-type = <4>; /* MIPI CSI-2 D-PHY */ + remote-endpoint = <&csi_in_mipi_csi2>; + }; + }; + }; + }; + +... From patchwork Fri Oct 23 17:45:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Kocialkowski X-Patchwork-Id: 11854309 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 335D6C4363A for ; Fri, 23 Oct 2020 17:51:08 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4A54B21582 for ; Fri, 23 Oct 2020 17:51:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="RtOT3Qxv" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4A54B21582 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=am3d08IYWJA41irsZcEp/bMCo+GHEhoqsXxlZElABHM=; b=RtOT3QxvkPgmE6pSlKpre4Yhk 2bdZH4FEz1qzPGT+VxL2sfadyM7Ml+hvkDn71n0kkQrmE/vQ5zvIjgN8Ayr463eQQUMcBcBWCsYb1 hJte3jpgENGipE5RxN4YxOWP6kIOO5m3qxxagj7dU4tiCAxuLKuLyd9prOJjaYVsk4PRSNTF9pjOk H4kLSN5gJceM6+xwsIyzk/LDd7+w2YcyF7FacppYBoUQBQrR+K3meS9dlGQn1MQDEEwTUGLZOTDLp CdZZU6So0rGDTv0zhTj47IcxEDb+d6/Y2L6D+O0KxMJ9TtkOQgeZcL+cnwVG7686igpZU+e3KMzUX MuJepq1Wg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW1BR-0001zl-QW; Fri, 23 Oct 2020 17:48:57 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW19B-0000tq-61 for linux-arm-kernel@lists.infradead.org; Fri, 23 Oct 2020 17:46:58 +0000 X-Originating-IP: 93.29.109.196 Received: from localhost.localdomain (196.109.29.93.rev.sfr.net [93.29.109.196]) (Authenticated sender: paul.kocialkowski@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 5F1F11BF214; Fri, 23 Oct 2020 17:46:34 +0000 (UTC) From: Paul Kocialkowski To: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linux-sunxi@googlegroups.com Subject: [PATCH 12/14] media: sunxi: Add support for the A83T MIPI CSI-2 controller Date: Fri, 23 Oct 2020 19:45:44 +0200 Message-Id: <20201023174546.504028-13-paul.kocialkowski@bootlin.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> References: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201023_134638_581362_557B1B6F X-CRM114-Status: GOOD ( 30.71 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hans Verkuil , Philipp Zabel , Thomas Petazzoni , Greg Kroah-Hartman , Helen Koike , Vinod Koul , Maxime Ripard , Kishon Vijay Abraham I , Paul Kocialkowski , Chen-Yu Tsai , Rob Herring , Hans Verkuil , Yong Deng , Sakari Ailus , Mauro Carvalho Chehab , kevin.lhopital@hotmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The A83T supports MIPI CSI-2 with a composite controller, covering both the protocol logic and the D-PHY implementation. This controller seems to be found on the A83T only and probably was abandonned since. This implementation splits the protocol and D-PHY registers and uses the PHY framework internally. The D-PHY is not registered as a standalone PHY driver since it cannot be used with any other controller. There are a few notable points about the controller: - The initialisation sequence involes writing specific magic init values that do not seem to make any particular sense given the concerned register fields. - Interrupts appear to be hitting regardless of the interrupt mask registers, which can cause a serious flood when transmission errors occur. This work is based on the first version of the driver submitted by Kévin L'hôpital, which was adapted to mainline from the Allwinner BSP. This version integrates MIPI CSI-2 support as a standalone V4L2 subdev instead of merging it in the sun6i-csi driver. It was tested on a Banana Pi M3 board with an OV8865 sensor in a 4-lane configuration. Signed-off-by: Paul Kocialkowski --- drivers/media/platform/sunxi/Kconfig | 1 + drivers/media/platform/sunxi/Makefile | 1 + .../sunxi/sun8i-a83t-mipi-csi2/Kconfig | 11 + .../sunxi/sun8i-a83t-mipi-csi2/Makefile | 4 + .../sun8i-a83t-mipi-csi2/sun8i_a83t_dphy.c | 92 +++ .../sun8i-a83t-mipi-csi2/sun8i_a83t_dphy.h | 39 + .../sun8i_a83t_mipi_csi2.c | 700 ++++++++++++++++++ .../sun8i_a83t_mipi_csi2.h | 196 +++++ 8 files changed, 1044 insertions(+) create mode 100644 drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/Kconfig create mode 100644 drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/Makefile create mode 100644 drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_dphy.c create mode 100644 drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_dphy.h create mode 100644 drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c create mode 100644 drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h diff --git a/drivers/media/platform/sunxi/Kconfig b/drivers/media/platform/sunxi/Kconfig index 9684e07454ad..db4c07be7e4c 100644 --- a/drivers/media/platform/sunxi/Kconfig +++ b/drivers/media/platform/sunxi/Kconfig @@ -3,3 +3,4 @@ source "drivers/media/platform/sunxi/sun4i-csi/Kconfig" source "drivers/media/platform/sunxi/sun6i-csi/Kconfig" source "drivers/media/platform/sunxi/sun6i-mipi-csi2/Kconfig" +source "drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/Kconfig" diff --git a/drivers/media/platform/sunxi/Makefile b/drivers/media/platform/sunxi/Makefile index 887a7cae8fca..9aa01cb01883 100644 --- a/drivers/media/platform/sunxi/Makefile +++ b/drivers/media/platform/sunxi/Makefile @@ -3,5 +3,6 @@ obj-y += sun4i-csi/ obj-y += sun6i-csi/ obj-y += sun6i-mipi-csi2/ +obj-y += sun8i-a83t-mipi-csi2/ obj-y += sun8i-di/ obj-y += sun8i-rotate/ diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/Kconfig b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/Kconfig new file mode 100644 index 000000000000..162f5d1dc25f --- /dev/null +++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +config VIDEO_SUN8I_A83T_MIPI_CSI2 + tristate "Allwinner A83T MIPI CSI-2 Controller and D-PHY Driver" + depends on VIDEO_V4L2 && COMMON_CLK + depends on ARCH_SUNXI || COMPILE_TEST + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + select REGMAP_MMIO + select V4L2_FWNODE + help + Support for the Allwinner A83T MIPI CSI-2 Controller and D-PHY. diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/Makefile b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/Makefile new file mode 100644 index 000000000000..1427d15a879a --- /dev/null +++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only +sun8i-a83t-mipi-csi2-y += sun8i_a83t_mipi_csi2.o sun8i_a83t_dphy.o + +obj-$(CONFIG_VIDEO_SUN8I_A83T_MIPI_CSI2) += sun8i-a83t-mipi-csi2.o diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_dphy.c b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_dphy.c new file mode 100644 index 000000000000..ebb504247956 --- /dev/null +++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_dphy.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020 Bootlin + * Author: Paul Kocialkowski + */ + +#include +#include + +#include "sun8i_a83t_dphy.h" +#include "sun8i_a83t_mipi_csi2.h" + +static int sun8i_a83t_dphy_set_mode(struct phy *dphy, enum phy_mode mode, + int submode) +{ + if (mode != PHY_MODE_MIPI_DPHY || + submode != PHY_MIPI_DPHY_SUBMODE_RX) + return -EINVAL; + + return 0; +}; + +static int sun8i_a83t_dphy_configure(struct phy *dphy, + union phy_configure_opts *opts) +{ + struct sun8i_a83t_mipi_csi2_dev *cdev = phy_get_drvdata(dphy); + int ret; + + ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy); + if (ret) + return ret; + + memcpy(&cdev->dphy_config, opts, sizeof(cdev->dphy_config)); + + return 0; +}; + +static int sun8i_a83t_dphy_power_on(struct phy *dphy) +{ + struct sun8i_a83t_mipi_csi2_dev *cdev = phy_get_drvdata(dphy); + struct regmap *regmap = cdev->regmap; + + regmap_write(regmap, SUN8I_A83T_DPHY_CTRL_REG, + SUN8I_A83T_DPHY_CTRL_RESET_N | + SUN8I_A83T_DPHY_CTRL_SHUTDOWN_N); + + regmap_write(regmap, SUN8I_A83T_DPHY_ANA0_REG, + SUN8I_A83T_DPHY_ANA0_REXT_EN | + SUN8I_A83T_DPHY_ANA0_RINT(2) | + SUN8I_A83T_DPHY_ANA0_SNK(2)); + + return 0; +}; + +static int sun8i_a83t_dphy_power_off(struct phy *dphy) +{ + struct sun8i_a83t_mipi_csi2_dev *cdev = phy_get_drvdata(dphy); + struct regmap *regmap = cdev->regmap; + + regmap_write(regmap, SUN8I_A83T_DPHY_CTRL_REG, 0); + + return 0; +}; + +static struct phy_ops sun8i_a83t_dphy_ops = { + .set_mode = sun8i_a83t_dphy_set_mode, + .configure = sun8i_a83t_dphy_configure, + .power_on = sun8i_a83t_dphy_power_on, + .power_off = sun8i_a83t_dphy_power_off, +}; + +int sun8i_a83t_dphy_register(struct sun8i_a83t_mipi_csi2_dev *cdev) +{ + struct phy_provider *phy_provider; + + cdev->dphy = devm_phy_create(cdev->dev, NULL, &sun8i_a83t_dphy_ops); + if (IS_ERR(cdev->dphy)) { + dev_err(cdev->dev, "failed to create D-PHY\n"); + return PTR_ERR(cdev->dphy); + } + + phy_set_drvdata(cdev->dphy, cdev); + + phy_provider = devm_of_phy_provider_register(cdev->dev, + of_phy_simple_xlate); + if (IS_ERR(phy_provider)) { + dev_err(cdev->dev, "failed to register D-PHY provider\n"); + return PTR_ERR(phy_provider); + } + + return 0; +} diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_dphy.h b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_dphy.h new file mode 100644 index 000000000000..a4ed355e5f6f --- /dev/null +++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_dphy.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2020 Kévin L'hôpital + * Copyright 2020 Bootlin + * Author: Paul Kocialkowski + */ + +#ifndef __SUN8I_A83T_DPHY_H__ +#define __SUN8I_A83T_DPHY_H__ + +#include "sun8i_a83t_mipi_csi2.h" + +#define SUN8I_A83T_DPHY_CTRL_REG 0x10 +#define SUN8I_A83T_DPHY_CTRL_INIT_VALUE 0xb8df698e +#define SUN8I_A83T_DPHY_CTRL_RESET_N BIT(31) +#define SUN8I_A83T_DPHY_CTRL_SHUTDOWN_N BIT(15) +#define SUN8I_A83T_DPHY_CTRL_DEBUG BIT(8) +#define SUN8I_A83T_DPHY_STATUS_REG 0x14 +#define SUN8I_A83T_DPHY_STATUS_CLK_STOP BIT(10) +#define SUN8I_A83T_DPHY_STATUS_CLK_ULPS BIT(9) +#define SUN8I_A83T_DPHY_STATUS_HSCLK BIT(8) +#define SUN8I_A83T_DPHY_STATUS_D3_STOP BIT(7) +#define SUN8I_A83T_DPHY_STATUS_D2_STOP BIT(6) +#define SUN8I_A83T_DPHY_STATUS_D1_STOP BIT(5) +#define SUN8I_A83T_DPHY_STATUS_D0_STOP BIT(4) +#define SUN8I_A83T_DPHY_STATUS_D3_ULPS BIT(3) +#define SUN8I_A83T_DPHY_STATUS_D2_ULPS BIT(2) +#define SUN8I_A83T_DPHY_STATUS_D1_ULPS BIT(1) +#define SUN8I_A83T_DPHY_STATUS_D0_ULPS BIT(0) + +#define SUN8I_A83T_DPHY_ANA0_REG 0x30 +#define SUN8I_A83T_DPHY_ANA0_REXT_EN BIT(31) +#define SUN8I_A83T_DPHY_ANA0_REXT BIT(30) +#define SUN8I_A83T_DPHY_ANA0_RINT(v) (((v) << 28) & GENMASK(29, 28)) +#define SUN8I_A83T_DPHY_ANA0_SNK(v) (((v) << 20) & GENMASK(22, 20)) + +int sun8i_a83t_dphy_register(struct sun8i_a83t_mipi_csi2_dev *cdev); + +#endif /* __SUN8I_A83T_DPHY_H__ */ diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c new file mode 100644 index 000000000000..1ff6f5dfd81a --- /dev/null +++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c @@ -0,0 +1,700 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020 Kévin L'hôpital + * Copyright 2020 Bootlin + * Author: Paul Kocialkowski + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sun8i_a83t_dphy.h" +#include "sun8i_a83t_mipi_csi2.h" + +#define MODULE_NAME "sun8i-a83t-mipi-csi2" + +/* Core */ + +static irqreturn_t sun8i_a83t_mipi_csi2_isr(int irq, void *dev_id) +{ + struct sun8i_a83t_mipi_csi2_dev *cdev = + (struct sun8i_a83t_mipi_csi2_dev *)dev_id; + struct regmap *regmap = cdev->regmap; + u32 status; + + WARN_ONCE(1, MODULE_NAME + ": Unsolicited interrupt, an error likely occurred!\n"); + + regmap_read(regmap, SUN8I_A83T_MIPI_CSI2_INT_STA0_REG, &status); + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_INT_STA0_REG, status); + + regmap_read(regmap, SUN8I_A83T_MIPI_CSI2_INT_STA1_REG, &status); + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_INT_STA1_REG, status); + + regmap_read(regmap, SUN8I_A83T_MIPI_CSI2_INT_MSK0_REG, &status); + regmap_read(regmap, SUN8I_A83T_MIPI_CSI2_INT_MSK1_REG, &status); + + /* + * The interrupt can be used to catch transmission errors. + * However, we currently lack plumbing for reporting that to the + * A31 CSI controller driver. + */ + + return IRQ_HANDLED; +} + +static void sun8i_a83t_mipi_csi2_init(struct sun8i_a83t_mipi_csi2_dev *cdev) +{ + struct regmap *regmap = cdev->regmap; + + /* + * The Allwinner BSP sets various magic values on a bunch of registers. + * This is apparently a necessary initialization process that will cause + * the capture to fail with unsolicited interrupts hitting if skipped. + * + * Most of the registers are set to proper values later, except for the + * two reserved registers. They are said to hold a "hardware lock" + * value, without more information available. + */ + + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_CTRL_REG, 0); + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_CTRL_REG, + SUN8I_A83T_MIPI_CSI2_CTRL_INIT_VALUE); + + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_RX_PKT_NUM_REG, 0); + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_RX_PKT_NUM_REG, + SUN8I_A83T_MIPI_CSI2_RX_PKT_NUM_INIT_VALUE); + + regmap_write(regmap, SUN8I_A83T_DPHY_CTRL_REG, 0); + regmap_write(regmap, SUN8I_A83T_DPHY_CTRL_REG, + SUN8I_A83T_DPHY_CTRL_INIT_VALUE); + + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_RSVD1_REG, 0); + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_RSVD1_REG, + SUN8I_A83T_MIPI_CSI2_RSVD1_HW_LOCK_VALUE); + + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_RSVD2_REG, 0); + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_RSVD2_REG, + SUN8I_A83T_MIPI_CSI2_RSVD2_HW_LOCK_VALUE); + + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_CFG_REG, 0); + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_CFG_REG, + SUN8I_A83T_MIPI_CSI2_CFG_INIT_VALUE); +} + +static int sun8i_a83t_mipi_csi2_s_power(struct v4l2_subdev *subdev, int on) +{ + struct sun8i_a83t_mipi_csi2_video *video = + sun8i_a83t_mipi_csi2_subdev_video(subdev); + struct sun8i_a83t_mipi_csi2_dev *cdev = sun8i_a83t_mipi_csi2_video_dev(video); + int ret; + + if (!on) { + clk_disable_unprepare(cdev->clk_mod); + clk_disable_unprepare(cdev->clk_mipi); + clk_disable_unprepare(cdev->clk_misc); + reset_control_assert(cdev->reset); + + return 0; + } + + ret = clk_prepare_enable(cdev->clk_mod); + if (ret) { + dev_err(cdev->dev, "failed to enable module clock\n"); + return ret; + } + + ret = clk_prepare_enable(cdev->clk_mipi); + if (ret) { + dev_err(cdev->dev, "failed to enable MIPI clock\n"); + goto error_clk_mod; + } + + ret = clk_prepare_enable(cdev->clk_misc); + if (ret) { + dev_err(cdev->dev, "failed to enable CSI misc clock\n"); + goto error_clk_mipi; + } + + ret = reset_control_deassert(cdev->reset); + if (ret) { + dev_err(cdev->dev, "failed to deassert reset\n"); + goto error_clk_misc; + } + + sun8i_a83t_mipi_csi2_init(cdev); + + return 0; + +error_clk_misc: + clk_disable_unprepare(cdev->clk_misc); + +error_clk_mipi: + clk_disable_unprepare(cdev->clk_mipi); + +error_clk_mod: + clk_disable_unprepare(cdev->clk_mod); + + return ret; +} + +static const struct v4l2_subdev_core_ops sun8i_a83t_mipi_csi2_subdev_core_ops = { + .s_power = sun8i_a83t_mipi_csi2_s_power, +}; + +/* Video */ + +static int sun8i_a83t_mipi_csi2_s_stream(struct v4l2_subdev *subdev, int on) +{ + struct sun8i_a83t_mipi_csi2_video *video = + sun8i_a83t_mipi_csi2_subdev_video(subdev); + struct sun8i_a83t_mipi_csi2_dev *cdev = sun8i_a83t_mipi_csi2_video_dev(video); + struct v4l2_subdev *remote_subdev = video->remote_subdev; + struct v4l2_fwnode_bus_mipi_csi2 *bus_mipi_csi2 = + &video->endpoint.bus.mipi_csi2; + union phy_configure_opts dphy_opts = { 0 }; + struct phy_configure_opts_mipi_dphy *dphy_cfg = &dphy_opts.mipi_dphy; + struct regmap *regmap = cdev->regmap; + struct v4l2_ctrl *ctrl; + unsigned int lanes_count; + unsigned int bpp; + unsigned long pixel_rate; + u8 data_type = 0; + u32 version = 0; + /* Initialize to 0 to use both in disable label (ret != 0) and off. */ + int ret = 0; + + if (!remote_subdev) + return -ENODEV; + + if (!on) { + v4l2_subdev_call(remote_subdev, video, s_stream, 0); + +disable: + regmap_update_bits(regmap, SUN8I_A83T_MIPI_CSI2_CFG_REG, + SUN8I_A83T_MIPI_CSI2_CFG_SYNC_EN, 0); + + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_CTRL_REG, 0); + + phy_power_off(cdev->dphy); + + return ret; + } + + switch (video->mbus_code) { + case MEDIA_BUS_FMT_SBGGR8_1X8: + case MEDIA_BUS_FMT_SGBRG8_1X8: + case MEDIA_BUS_FMT_SGRBG8_1X8: + case MEDIA_BUS_FMT_SRGGB8_1X8: + data_type = MIPI_CSI2_DATA_TYPE_RAW8; + bpp = 8; + break; + case MEDIA_BUS_FMT_SBGGR10_1X10: + case MEDIA_BUS_FMT_SGBRG10_1X10: + case MEDIA_BUS_FMT_SGRBG10_1X10: + case MEDIA_BUS_FMT_SRGGB10_1X10: + data_type = MIPI_CSI2_DATA_TYPE_RAW10; + bpp = 10; + break; + default: + return -EINVAL; + } + + /* Sensor pixel rate */ + + ctrl = v4l2_ctrl_find(remote_subdev->ctrl_handler, V4L2_CID_PIXEL_RATE); + if (!ctrl) { + dev_err(cdev->dev, + "%s: no MIPI CSI-2 pixel rate from the sensor\n", + __func__); + return -ENODEV; + } + + pixel_rate = (unsigned long)v4l2_ctrl_g_ctrl_int64(ctrl); + if (!pixel_rate) { + dev_err(cdev->dev, + "%s: zero MIPI CSI-2 pixel rate from the sensor\n", + __func__); + return -ENODEV; + } + + /* D-PHY configuration */ + + lanes_count = bus_mipi_csi2->num_data_lanes; + phy_mipi_dphy_get_default_config(pixel_rate, bpp, lanes_count, + dphy_cfg); + + /* + * Note that our hardware is using DDR, which is not taken in account by + * phy_mipi_dphy_get_default_config when calculating hs_clk_rate from + * the pixel rate, lanes count and bpp. + * + * The resulting clock rate is basically the symbol rate over the whole + * link. The actual clock rate is calculated with division by two since + * DDR samples both on rising and falling edges. + */ + + dev_dbg(cdev->dev, "A83T MIPI CSI-2 config:\n"); + dev_dbg(cdev->dev, + "%ld pixels/s, %u bits/pixel, %u lanes, %lu Hz clock\n", + pixel_rate, bpp, lanes_count, dphy_cfg->hs_clk_rate / 2); + + ret = 0; + ret |= phy_reset(cdev->dphy); + ret |= phy_set_mode_ext(cdev->dphy, PHY_MODE_MIPI_DPHY, + PHY_MIPI_DPHY_SUBMODE_RX); + ret |= phy_configure(cdev->dphy, &dphy_opts); + + if (ret) { + dev_err(cdev->dev, "Failed to setup MIPI D-PHY\n"); + return ret; + } + + ret = phy_power_on(cdev->dphy); + if (ret) { + dev_err(cdev->dev, "Failed to power on MIPI D-PHY\n"); + return ret; + } + + /* MIPI CSI-2 controller setup */ + + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_CTRL_REG, + SUN8I_A83T_MIPI_CSI2_CTRL_RESET_N); + + regmap_read(regmap, SUN8I_A83T_MIPI_CSI2_VERSION_REG, &version); + + dev_dbg(cdev->dev, "A83T MIPI CSI-2 version: %04x\n", version); + + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_CFG_REG, + SUN8I_A83T_MIPI_CSI2_CFG_UNPKT_EN | + SUN8I_A83T_MIPI_CSI2_CFG_SYNC_DLY_CYCLE(8) | + SUN8I_A83T_MIPI_CSI2_CFG_N_CHANNEL(1) | + SUN8I_A83T_MIPI_CSI2_CFG_N_LANE(lanes_count)); + + regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_VCDT0_REG, + SUN8I_A83T_MIPI_CSI2_VCDT0_CH_VC(3, 3) | + SUN8I_A83T_MIPI_CSI2_VCDT0_CH_VC(2, 2) | + SUN8I_A83T_MIPI_CSI2_VCDT0_CH_VC(1, 1) | + SUN8I_A83T_MIPI_CSI2_VCDT0_CH_VC(0, 0) | + SUN8I_A83T_MIPI_CSI2_VCDT0_CH_DT(0, data_type)); + + /* Start streaming. */ + regmap_update_bits(regmap, SUN8I_A83T_MIPI_CSI2_CFG_REG, + SUN8I_A83T_MIPI_CSI2_CFG_SYNC_EN, + SUN8I_A83T_MIPI_CSI2_CFG_SYNC_EN); + + ret = v4l2_subdev_call(remote_subdev, video, s_stream, 1); + if (ret) + goto disable; + + return 0; +} + +static const struct v4l2_subdev_video_ops sun8i_a83t_mipi_csi2_subdev_video_ops = { + .s_stream = sun8i_a83t_mipi_csi2_s_stream, +}; + +/* Pad */ + +static int sun8i_a83t_mipi_csi2_enum_mbus_code(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *config, + struct v4l2_subdev_mbus_code_enum *code_enum) +{ + struct sun8i_a83t_mipi_csi2_video *video = + sun8i_a83t_mipi_csi2_subdev_video(subdev); + + if (!video->remote_subdev) + return -ENODEV; + + /* Forward to the sensor. */ + code_enum->pad = video->remote_pad_index; + + return v4l2_subdev_call(video->remote_subdev, pad, enum_mbus_code, + config, code_enum); +} + +static int sun8i_a83t_mipi_csi2_get_fmt(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *config, + struct v4l2_subdev_format *format) +{ + struct sun8i_a83t_mipi_csi2_video *video = + sun8i_a83t_mipi_csi2_subdev_video(subdev); + + if (!video->remote_subdev) + return -ENODEV; + + /* Forward to the sensor. */ + format->pad = video->remote_pad_index; + + return v4l2_subdev_call(video->remote_subdev, pad, get_fmt, config, + format); +} + +static int sun8i_a83t_mipi_csi2_set_fmt(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *config, + struct v4l2_subdev_format *format) +{ + struct sun8i_a83t_mipi_csi2_video *video = + sun8i_a83t_mipi_csi2_subdev_video(subdev); + + if (!video->remote_subdev) + return -ENODEV; + + /* Forward to the sensor. */ + format->pad = video->remote_pad_index; + + return v4l2_subdev_call(video->remote_subdev, pad, set_fmt, config, + format); +} + +static int sun8i_a83t_mipi_csi2_enum_frame_size(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *config, + struct v4l2_subdev_frame_size_enum *size_enum) +{ + struct sun8i_a83t_mipi_csi2_video *video = + sun8i_a83t_mipi_csi2_subdev_video(subdev); + + if (!video->remote_subdev) + return -ENODEV; + + /* Forward to the sensor. */ + size_enum->pad = video->remote_pad_index; + + return v4l2_subdev_call(video->remote_subdev, pad, enum_frame_size, + config, size_enum); +} + +static int sun8i_a83t_mipi_csi2_enum_frame_interval(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *config, + struct v4l2_subdev_frame_interval_enum *interval_enum) +{ + struct sun8i_a83t_mipi_csi2_video *video = + sun8i_a83t_mipi_csi2_subdev_video(subdev); + + if (!video->remote_subdev) + return -ENODEV; + + /* Forward to the sensor. */ + interval_enum->pad = video->remote_pad_index; + + return v4l2_subdev_call(video->remote_subdev, pad, enum_frame_interval, + config, interval_enum); +} + +static const struct v4l2_subdev_pad_ops sun8i_a83t_mipi_csi2_subdev_pad_ops = { + .enum_mbus_code = sun8i_a83t_mipi_csi2_enum_mbus_code, + .get_fmt = sun8i_a83t_mipi_csi2_get_fmt, + .set_fmt = sun8i_a83t_mipi_csi2_set_fmt, + .enum_frame_size = sun8i_a83t_mipi_csi2_enum_frame_size, + .enum_frame_interval = sun8i_a83t_mipi_csi2_enum_frame_interval, +}; + +/* Subdev */ + +static const struct v4l2_subdev_ops sun8i_a83t_mipi_csi2_subdev_ops = { + .core = &sun8i_a83t_mipi_csi2_subdev_core_ops, + .video = &sun8i_a83t_mipi_csi2_subdev_video_ops, + .pad = &sun8i_a83t_mipi_csi2_subdev_pad_ops, +}; + +/* Notifier */ + +static int sun8i_a83t_mipi_csi2_notifier_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *remote_subdev, + struct v4l2_async_subdev *remote_subdev_async) +{ + struct v4l2_subdev *subdev = notifier->sd; + struct sun8i_a83t_mipi_csi2_video *video = + sun8i_a83t_mipi_csi2_subdev_video(subdev); + struct sun8i_a83t_mipi_csi2_dev *cdev = sun8i_a83t_mipi_csi2_video_dev(video); + int source_pad; + int ret; + + source_pad = media_entity_get_fwnode_pad(&remote_subdev->entity, + remote_subdev->fwnode, + MEDIA_PAD_FL_SOURCE); + if (source_pad < 0) + return source_pad; + + ret = media_create_pad_link(&remote_subdev->entity, source_pad, + &subdev->entity, 0, + MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); + if (ret) { + dev_err(cdev->dev, "failed to create %s:%u -> %s:%u link\n", + remote_subdev->entity.name, source_pad, + subdev->entity.name, 0); + return ret; + } + + video->remote_subdev = remote_subdev; + video->remote_pad_index = source_pad; + + return 0; +} + +static const struct v4l2_async_notifier_operations sun8i_a83t_mipi_csi2_notifier_ops = { + .bound = sun8i_a83t_mipi_csi2_notifier_bound, +}; + +/* Media Entity */ + +static int sun8i_a83t_mipi_csi2_link_validate(struct media_link *link) +{ + struct v4l2_subdev *subdev = + container_of(link->sink->entity, struct v4l2_subdev, entity); + struct sun8i_a83t_mipi_csi2_video *video = + sun8i_a83t_mipi_csi2_subdev_video(subdev); + struct v4l2_subdev *remote_subdev; + struct v4l2_subdev_format format = { 0 }; + int ret; + + if (!is_media_entity_v4l2_subdev(link->source->entity)) + return -EINVAL; + + remote_subdev = media_entity_to_v4l2_subdev(link->source->entity); + + format.which = V4L2_SUBDEV_FORMAT_ACTIVE; + format.pad = link->source->index; + + ret = v4l2_subdev_call(remote_subdev, pad, get_fmt, NULL, &format); + if (ret) + return ret; + + video->mbus_code = format.format.code; + + return 0; +} + +static const struct media_entity_operations sun8i_a83t_mipi_csi2_entity_ops = { + .link_validate = sun8i_a83t_mipi_csi2_link_validate, +}; + +/* Base Driver */ + +static int sun8i_a83t_mipi_csi2_v4l2_setup(struct sun8i_a83t_mipi_csi2_dev *cdev) +{ + struct sun8i_a83t_mipi_csi2_video *video = &cdev->video; + struct v4l2_subdev *subdev = &video->subdev; + struct v4l2_async_notifier *notifier = &video->notifier; + struct fwnode_handle *handle; + struct v4l2_fwnode_endpoint *endpoint; + int ret; + + /* Subdev */ + + v4l2_subdev_init(subdev, &sun8i_a83t_mipi_csi2_subdev_ops); + subdev->dev = cdev->dev; + strscpy(subdev->name, MODULE_NAME, sizeof(subdev->name)); + v4l2_set_subdevdata(subdev, cdev); + + /* Entity */ + + subdev->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; + subdev->entity.ops = &sun8i_a83t_mipi_csi2_entity_ops; + + /* Pads */ + + video->pads[0].flags = MEDIA_PAD_FL_SINK; + video->pads[1].flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(&subdev->entity, 2, video->pads); + if (ret) + return ret; + + /* Endpoint */ + + handle = fwnode_graph_get_endpoint_by_id(dev_fwnode(cdev->dev), 0, 0, + FWNODE_GRAPH_ENDPOINT_NEXT); + if (!handle) + goto error_media_entity; + + endpoint = &video->endpoint; + endpoint->bus_type = V4L2_MBUS_CSI2_DPHY; + + ret = v4l2_fwnode_endpoint_parse(handle, endpoint); + fwnode_handle_put(handle); + if (ret) + goto error_media_entity; + + /* Notifier */ + + v4l2_async_notifier_init(notifier); + + ret = v4l2_async_notifier_add_fwnode_remote_subdev(notifier, handle, + &video->subdev_async); + if (ret) + goto error_media_entity; + + video->notifier.ops = &sun8i_a83t_mipi_csi2_notifier_ops; + + ret = v4l2_async_subdev_notifier_register(subdev, notifier); + if (ret < 0) + goto error_notifier; + + /* Subdev */ + + ret = v4l2_async_register_subdev(subdev); + if (ret < 0) + goto error_notifier_registered; + + return 0; + +error_notifier_registered: + v4l2_async_notifier_unregister(notifier); +error_notifier: + v4l2_async_notifier_cleanup(notifier); +error_media_entity: + media_entity_cleanup(&subdev->entity); + + return ret; +} + +static int sun8i_a83t_mipi_csi2_v4l2_teardown(struct sun8i_a83t_mipi_csi2_dev *cdev) +{ + struct sun8i_a83t_mipi_csi2_video *video = &cdev->video; + struct v4l2_subdev *subdev = &video->subdev; + struct v4l2_async_notifier *notifier = &video->notifier; + + v4l2_async_unregister_subdev(subdev); + v4l2_async_notifier_unregister(notifier); + v4l2_async_notifier_cleanup(notifier); + media_entity_cleanup(&subdev->entity); + v4l2_device_unregister_subdev(subdev); + + return 0; +} + +static const struct regmap_config sun8i_a83t_mipi_csi2_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x120, +}; + +static int sun8i_a83t_mipi_csi2_resource_request(struct sun8i_a83t_mipi_csi2_dev *cdev, + struct platform_device *pdev) +{ + struct resource *res; + void __iomem *io_base; + int irq; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + io_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(io_base)) + return PTR_ERR(io_base); + + cdev->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "bus", io_base, + &sun8i_a83t_mipi_csi2_regmap_config); + if (IS_ERR(cdev->regmap)) { + dev_err(&pdev->dev, "failed to init register map\n"); + return PTR_ERR(cdev->regmap); + } + + cdev->clk_mod = devm_clk_get(&pdev->dev, "mod"); + if (IS_ERR(cdev->clk_mod)) { + dev_err(&pdev->dev, "failed to acquire csi clock\n"); + return PTR_ERR(cdev->clk_mod); + } + + cdev->clk_mipi = devm_clk_get(&pdev->dev, "mipi"); + if (IS_ERR(cdev->clk_mod)) { + dev_err(&pdev->dev, "failed to acquire mipi clock\n"); + return PTR_ERR(cdev->clk_mipi); + } + + cdev->clk_misc = devm_clk_get(&pdev->dev, "misc"); + if (IS_ERR(cdev->clk_mod)) { + dev_err(&pdev->dev, "failed to acquire misc clock\n"); + return PTR_ERR(cdev->clk_misc); + } + + cdev->reset = devm_reset_control_get_shared(&pdev->dev, NULL); + if (IS_ERR(cdev->reset)) { + dev_err(&pdev->dev, "failed to get reset controller\n"); + return PTR_ERR(cdev->reset); + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return -ENXIO; + + ret = devm_request_irq(&pdev->dev, irq, sun8i_a83t_mipi_csi2_isr, 0, + MODULE_NAME, cdev); + if (ret) { + dev_err(&pdev->dev, "failed to request MIPI CSI-2 IRQ\n"); + return ret; + } + + ret = sun8i_a83t_dphy_register(cdev); + if (ret) { + dev_err(&pdev->dev, "failed to init MIPI D-PHY\n"); + return ret; + } + + return 0; +} + +static int sun8i_a83t_mipi_csi2_probe(struct platform_device *pdev) +{ + struct sun8i_a83t_mipi_csi2_dev *cdev; + int ret; + + cdev = devm_kzalloc(&pdev->dev, sizeof(*cdev), GFP_KERNEL); + if (!cdev) + return -ENOMEM; + + cdev->dev = &pdev->dev; + + ret = sun8i_a83t_mipi_csi2_resource_request(cdev, pdev); + if (ret) + return ret; + + platform_set_drvdata(pdev, cdev); + + ret = sun8i_a83t_mipi_csi2_v4l2_setup(cdev); + if (ret) + return ret; + + return 0; +} + +static int sun8i_a83t_mipi_csi2_remove(struct platform_device *pdev) +{ + struct sun8i_a83t_mipi_csi2_dev *cdev = platform_get_drvdata(pdev); + + phy_exit(cdev->dphy); + + return sun8i_a83t_mipi_csi2_v4l2_teardown(cdev); +} + +static const struct of_device_id sun8i_a83t_mipi_csi2_of_match[] = { + { .compatible = "allwinner,sun8i-a83t-mipi-csi2" }, + {}, +}; +MODULE_DEVICE_TABLE(of, sun8i_a83t_mipi_csi2_of_match); + +static struct platform_driver sun8i_a83t_mipi_csi2_platform_driver = { + .probe = sun8i_a83t_mipi_csi2_probe, + .remove = sun8i_a83t_mipi_csi2_remove, + .driver = { + .name = MODULE_NAME, + .of_match_table = of_match_ptr(sun8i_a83t_mipi_csi2_of_match), + }, +}; +module_platform_driver(sun8i_a83t_mipi_csi2_platform_driver); + +MODULE_DESCRIPTION("Allwinner A83T MIPI CSI-2 and D-PHY Controller Driver"); +MODULE_AUTHOR("Paul Kocialkowski "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h new file mode 100644 index 000000000000..f256c796d07c --- /dev/null +++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.h @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2020 Kévin L'hôpital + * Copyright 2020 Bootlin + * Author: Paul Kocialkowski + */ + +#ifndef __SUN8I_A83T_MIPI_CSI2_H__ +#define __SUN8I_A83T_MIPI_CSI2_H__ + +#include +#include +#include +#include +#include + +#define SUN8I_A83T_MIPI_CSI2_VERSION_REG 0x0 +#define SUN8I_A83T_MIPI_CSI2_CTRL_REG 0x4 +#define SUN8I_A83T_MIPI_CSI2_CTRL_INIT_VALUE 0xb8c39bec +#define SUN8I_A83T_MIPI_CSI2_CTRL_RESET_N BIT(31) +#define SUN8I_A83T_MIPI_CSI2_RX_PKT_NUM_REG 0x8 +#define SUN8I_A83T_MIPI_CSI2_RX_PKT_NUM_INIT_VALUE 0xb8d257f8 +#define SUN8I_A83T_MIPI_CSI2_RSVD0_REG 0xc + +#define SUN8I_A83T_MIPI_CSI2_RSVD1_REG 0x18 +#define SUN8I_A83T_MIPI_CSI2_RSVD1_HW_LOCK_VALUE 0xb8c8a30c +#define SUN8I_A83T_MIPI_CSI2_RSVD2_REG 0x1c +#define SUN8I_A83T_MIPI_CSI2_RSVD2_HW_LOCK_VALUE 0xb8df8ad7 +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_REG 0x20 +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_ECC_ERR_DBL BIT(28) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_LINE_CKSM_ERR_VC3 BIT(27) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_LINE_CKSM_ERR_VC2 BIT(26) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_LINE_CKSM_ERR_VC1 BIT(25) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_LINE_CKSM_ERR_VC0 BIT(24) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_LINE_SEQ_ERR_DT3 BIT(23) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_LINE_SEQ_ERR_DT2 BIT(22) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_LINE_SEQ_ERR_DT1 BIT(21) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_LINE_SEQ_ERR_DT0 BIT(20) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_LS_LE_ERR_DT3 BIT(19) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_LS_LE_ERR_DT2 BIT(18) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_LS_LE_ERR_DT1 BIT(17) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_LS_LE_ERR_DT0 BIT(16) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_CRC_ERR_VC3 BIT(15) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_CRC_ERR_VC2 BIT(14) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_CRC_ERR_VC1 BIT(13) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_CRC_ERR_VC0 BIT(12) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_FRM_SEQ_ERR_VC3 BIT(11) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_FRM_SEQ_ERR_VC2 BIT(10) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_FRM_SEQ_ERR_VC1 BIT(9) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_FRM_SEQ_ERR_VC0 BIT(8) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_FS_FE_ERR_VC3 BIT(7) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_FS_FE_ERR_VC2 BIT(6) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_FS_FE_ERR_VC1 BIT(5) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_FS_FE_ERR_VC0 BIT(4) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_SOT_SYNC_ERR_3 BIT(3) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_SOT_SYNC_ERR_2 BIT(2) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_SOT_SYNC_ERR_1 BIT(1) +#define SUN8I_A83T_MIPI_CSI2_INT_STA0_SOT_SYNC_ERR_0 BIT(0) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_REG 0x24 +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_LINE_SEQ_ERR_DT7 BIT(23) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_LINE_SEQ_ERR_DT6 BIT(22) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_LINE_SEQ_ERR_DT5 BIT(21) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_LINE_SEQ_ERR_DT4 BIT(20) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_LS_LE_ERR_DT7 BIT(19) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_LS_LE_ERR_DT6 BIT(18) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_LS_LE_ERR_DT5 BIT(17) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_LS_LE_ERR_DT4 BIT(16) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_DT_ERR_VC3 BIT(15) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_DT_ERR_VC2 BIT(14) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_DT_ERR_VC1 BIT(13) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_DT_ERR_VC0 BIT(12) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_ECC_ERR1_VC3 BIT(11) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_ECC_ERR1_VC2 BIT(10) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_ECC_ERR1_VC1 BIT(9) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_ECC_ERR1_VC0 BIT(8) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_SOT_ERR_3 BIT(7) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_SOT_ERR_2 BIT(6) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_SOT_ERR_1 BIT(5) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_SOT_ERR_0 BIT(4) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_ESC_ENTRY_ERR_3 BIT(3) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_ESC_ENTRY_ERR_2 BIT(2) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_ESC_ENTRY_ERR_1 BIT(1) +#define SUN8I_A83T_MIPI_CSI2_INT_STA1_ESC_ENTRY_ERR_0 BIT(0) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_REG 0x28 +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_ECC_ERR_DBL BIT(28) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_CKSM_ERR_VC3 BIT(27) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_CKSM_ERR_VC2 BIT(26) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_CKSM_ERR_VC1 BIT(25) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_CKSM_ERR_VC0 BIT(24) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_LINE_SEQ_ERR_DT3 BIT(23) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_LINE_SEQ_ERR_DT2 BIT(22) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_LINE_SEQ_ERR_DT1 BIT(21) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_LINE_SEQ_ERR_DT0 BIT(20) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_LS_LE_ERR_DT3 BIT(19) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_LS_LE_ERR_DT2 BIT(18) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_LS_LE_ERR_DT1 BIT(17) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_LS_LE_ERR_DT0 BIT(16) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_CRC_ERR_VC3 BIT(15) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_CRC_ERR_VC2 BIT(14) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_CRC_ERR_VC1 BIT(13) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_CRC_ERR_VC0 BIT(12) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_FRM_SEQ_ERR_VC3 BIT(11) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_FRM_SEQ_ERR_VC2 BIT(10) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_FRM_SEQ_ERR_VC1 BIT(9) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_FRM_SEQ_ERR_VC0 BIT(8) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_FS_FE_ERR_VC3 BIT(7) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_FS_FE_ERR_VC2 BIT(6) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_FS_FE_ERR_VC1 BIT(5) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_FS_FE_ERR_VC0 BIT(4) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_SOT_SYNC_ERR_3 BIT(3) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_SOT_SYNC_ERR_2 BIT(2) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_SOT_SYNC_ERR_1 BIT(1) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK0_SOT_SYNC_ERR_0 BIT(0) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_REG 0x2c +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_DT_ERR_VC3 BIT(15) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_DT_ERR_VC2 BIT(14) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_DT_ERR_VC1 BIT(13) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_DT_ERR_VC0 BIT(12) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_ECC_ERR1_VC3 BIT(11) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_ECC_ERR1_VC2 BIT(10) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_ECC_ERR1_VC1 BIT(9) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_ECC_ERR1_VC0 BIT(8) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_SOT_ERR_3 BIT(7) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_SOT_ERR_2 BIT(6) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_SOT_ERR_1 BIT(5) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_SOT_ERR_0 BIT(4) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_ESC_ENTRY_ERR_3 BIT(3) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_ESC_ENTRY_ERR_2 BIT(2) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_ESC_ENTRY_ERR_1 BIT(1) +#define SUN8I_A83T_MIPI_CSI2_INT_MSK1_ESC_ENTRY_ERR_0 BIT(0) + +#define SUN8I_A83T_MIPI_CSI2_CFG_REG 0x100 +#define SUN8I_A83T_MIPI_CSI2_CFG_INIT_VALUE 0xb8c64f24 +#define SUN8I_A83T_MIPI_CSI2_CFG_SYNC_EN BIT(31) +#define SUN8I_A83T_MIPI_CSI2_CFG_BYPASS_ECC_EN BIT(29) +#define SUN8I_A83T_MIPI_CSI2_CFG_UNPKT_EN BIT(28) +#define SUN8I_A83T_MIPI_CSI2_CFG_NONE_UNPKT_RX_MODE BIT(27) +#define SUN8I_A83T_MIPI_CSI2_CFG_YC_SWAB BIT(26) +#define SUN8I_A83T_MIPI_CSI2_CFG_N_BYTE BIT(24) +#define SUN8I_A83T_MIPI_CSI2_CFG_SYNC_DLY_CYCLE(v) (((v) << 18) & \ + GENMASK(22, 18)) +#define SUN8I_A83T_MIPI_CSI2_CFG_N_CHANNEL(v) ((((v) - 1) << 16) & \ + GENMASK(17, 16)) +#define SUN8I_A83T_MIPI_CSI2_CFG_N_LANE(v) ((((v) - 1) << 4) & \ + GENMASK(5, 4)) +#define SUN8I_A83T_MIPI_CSI2_VCDT0_REG 0x104 +#define SUN8I_A83T_MIPI_CSI2_VCDT0_CH_VC(ch, vc) (((vc) & GENMASK(1, 0)) << \ + ((ch) * 8 + 6)) +#define SUN8I_A83T_MIPI_CSI2_VCDT0_CH_DT(ch, t) (((t) & GENMASK(5, 0)) << \ + ((ch) * 8)) +#define SUN8I_A83T_MIPI_CSI2_VCDT1_REG 0x108 +#define SUN8I_A83T_MIPI_CSI2_VCDT1_CH_VC(ch, vc) (((vc) & GENMASK(1, 0)) << \ + (((ch) - 4) * 8 + 6)) +#define SUN8I_A83T_MIPI_CSI2_VCDT1_CH_DT(ch, t) (((t) & GENMASK(5, 0)) << \ + (((ch) - 4) * 8)) + +enum mipi_csi2_data_type { + MIPI_CSI2_DATA_TYPE_RAW8 = 0x2a, + MIPI_CSI2_DATA_TYPE_RAW10 = 0x2b, + MIPI_CSI2_DATA_TYPE_RAW12 = 0x2c, +}; + +struct sun8i_a83t_mipi_csi2_video { + struct v4l2_fwnode_endpoint endpoint; + struct v4l2_subdev subdev; + struct media_pad pads[2]; + + struct v4l2_async_subdev subdev_async; + struct v4l2_async_notifier notifier; + + struct v4l2_subdev *remote_subdev; + u32 remote_pad_index; + u32 mbus_code; +}; + +struct sun8i_a83t_mipi_csi2_dev { + struct device *dev; + + struct regmap *regmap; + struct clk *clk_mod; + struct clk *clk_mipi; + struct clk *clk_misc; + struct reset_control *reset; + struct phy *dphy; + struct phy_configure_opts_mipi_dphy dphy_config; + + struct sun8i_a83t_mipi_csi2_video video; +}; + +#define sun8i_a83t_mipi_csi2_subdev_video(subdev) \ + container_of(subdev, struct sun8i_a83t_mipi_csi2_video, subdev) + +#define sun8i_a83t_mipi_csi2_video_dev(video) \ + container_of(video, struct sun8i_a83t_mipi_csi2_dev, video) + +#endif /* __SUN8I_A83T_MIPI_CSI2_H__ */ From patchwork Fri Oct 23 17:45:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Kocialkowski X-Patchwork-Id: 11854301 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6122DC4363A for ; Fri, 23 Oct 2020 17:50:25 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E1DCC21582 for ; Fri, 23 Oct 2020 17:50:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="l8XOoSIj" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E1DCC21582 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=YrlA3wCb9AyF8JKzjJrG5DC4jnGt7MLJn37cNG2YhFg=; b=l8XOoSIjbi5zfBrZoqohuppel 5kNHh37ScQ0X4KEk51arhjR4ysd3SMKiYATTWAWAbyRVzAF0ImBXA/3jc3r810aI0XIYsYExfW/6u 761eahMv8gsNZYdBFQtOAyivNnZ0yUJX/eHCG+oy3qja5stQHArZ7tg743hIlscGLP9GFYswC4Unq uvi7vEQBEnD3+x39gyOLoRRgkEisk+BufWPt16INYwUxGFonbMinTricqbxP2kk23DDS0Q84Ft7kh +GmBgMlcdaRi5NZzgbSbEMl3GUIs1/P9xdVN7e53FpmiLvFsl+fhtagac9dbv35eBA21kXAB19Vo9 nbd1URFEA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW1Ax-0001iv-6j; Fri, 23 Oct 2020 17:48:27 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW19C-0000u9-R2 for linux-arm-kernel@lists.infradead.org; Fri, 23 Oct 2020 17:46:46 +0000 X-Originating-IP: 93.29.109.196 Received: from localhost.localdomain (196.109.29.93.rev.sfr.net [93.29.109.196]) (Authenticated sender: paul.kocialkowski@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 3721A1BF209; Fri, 23 Oct 2020 17:46:36 +0000 (UTC) From: Paul Kocialkowski To: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linux-sunxi@googlegroups.com Subject: [PATCH 13/14] ARM: dts: sun8i: a83t: Add MIPI CSI-2 controller node Date: Fri, 23 Oct 2020 19:45:45 +0200 Message-Id: <20201023174546.504028-14-paul.kocialkowski@bootlin.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> References: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201023_134639_046957_71B0EBC7 X-CRM114-Status: GOOD ( 12.68 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hans Verkuil , Philipp Zabel , Thomas Petazzoni , Greg Kroah-Hartman , Helen Koike , Vinod Koul , Maxime Ripard , Kishon Vijay Abraham I , Paul Kocialkowski , Chen-Yu Tsai , Rob Herring , Hans Verkuil , Yong Deng , Sakari Ailus , Mauro Carvalho Chehab , kevin.lhopital@hotmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org MIPI CSI-2 is supported on the A83T with a dedicated controller that covers both the protocol and D-PHY. It can be connected to the CSI interface as a V4L2 subdev through the fwnode graph. Signed-off-by: Paul Kocialkowski --- arch/arm/boot/dts/sun8i-a83t.dtsi | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi index c010b27fdb6a..99e07012aee7 100644 --- a/arch/arm/boot/dts/sun8i-a83t.dtsi +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi @@ -1066,6 +1066,32 @@ csi_in: port { }; }; + mipi_csi2: mipi-csi2@1cb1000 { + compatible = "allwinner,sun8i-a83t-mipi-csi2"; + reg = <0x01cb1000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_BUS_CSI>, + <&ccu CLK_CSI_SCLK>, + <&ccu CLK_MIPI_CSI>, + <&ccu CLK_CSI_MISC>; + clock-names = "bus", "mod", "mipi", "misc"; + resets = <&ccu RST_BUS_CSI>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + mipi_csi2_in: port@0 { + reg = <0>; + }; + + mipi_csi2_out: port@1 { + reg = <1>; + }; + }; + }; + hdmi: hdmi@1ee0000 { compatible = "allwinner,sun8i-a83t-dw-hdmi"; reg = <0x01ee0000 0x10000>; From patchwork Fri Oct 23 17:45:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Kocialkowski X-Patchwork-Id: 11854305 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EBFDDC4363A for ; Fri, 23 Oct 2020 17:50:41 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7D78421582 for ; Fri, 23 Oct 2020 17:50:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="wAC8cKoh" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7D78421582 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=mjTjG6g8ph8wE1m2ULmJpNu0/SJBUGSjOYzTfcgHi+4=; b=wAC8cKoh9v1qg1ciYlkIfDaRg l/37Na6RG+UyMw7IvKZ2rg1hxNO3PbEH8tXWoq8j8S82mQHxvb/LvLidoBKc49f29VXphwIjeeR4k M5MtFW4O2fjJpOsrzl7uYieHMsKcXMGtELnf5yNmo2ig6YD0Vnm5Jsi+b3YXLQ34PoS7Qyn8oLvFv AIroKLXhucxJO6PZHlojDbCtiT2+2iJp1b+a7vQRVhdNIq5YQlsVUWzgPpcuUrhQHn7A4Oml7jfLq LHUX3nmLnRYQGRigC4il2xC2JjAEyLdROB/btbxuo0SDOUDBqJthOqa+6OIf5PjhfUwbSdgLU9pNr qAEiAtC9w==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW1B6-0001oT-D4; Fri, 23 Oct 2020 17:48:36 +0000 Received: from relay8-d.mail.gandi.net ([217.70.183.201]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kW19E-0000vT-Ip for linux-arm-kernel@lists.infradead.org; Fri, 23 Oct 2020 17:46:49 +0000 X-Originating-IP: 93.29.109.196 Received: from localhost.localdomain (196.109.29.93.rev.sfr.net [93.29.109.196]) (Authenticated sender: paul.kocialkowski@bootlin.com) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 02EB11BF203; Fri, 23 Oct 2020 17:46:37 +0000 (UTC) From: Paul Kocialkowski To: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, linux-sunxi@googlegroups.com Subject: [PATCH 14/14] media: sunxi: sun8i-a83t-mipi-csi2: Avoid using the (unsolicited) interrupt Date: Fri, 23 Oct 2020 19:45:46 +0200 Message-Id: <20201023174546.504028-15-paul.kocialkowski@bootlin.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> References: <20201023174546.504028-1-paul.kocialkowski@bootlin.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201023_134640_958540_A2CDC76D X-CRM114-Status: GOOD ( 15.26 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hans Verkuil , Philipp Zabel , Thomas Petazzoni , Greg Kroah-Hartman , Helen Koike , Vinod Koul , Maxime Ripard , Kishon Vijay Abraham I , Paul Kocialkowski , Chen-Yu Tsai , Rob Herring , Hans Verkuil , Yong Deng , Sakari Ailus , Mauro Carvalho Chehab , kevin.lhopital@hotmail.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The A83T MIPI CSI-2 apparently produces interrupts regardless of the mask registers, for example when a transmission error occurs. This generates quite a flood when unsolicited interrupts are received on each received frame. As a result, disable the interrupt for now since we are not currently using it for error reporting. Signed-off-by: Paul Kocialkowski --- .../sun8i_a83t_mipi_csi2.c | 40 ------------------- 1 file changed, 40 deletions(-) diff --git a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c index 1ff6f5dfd81a..26af3e3f5f89 100644 --- a/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c +++ b/drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c @@ -25,34 +25,6 @@ /* Core */ -static irqreturn_t sun8i_a83t_mipi_csi2_isr(int irq, void *dev_id) -{ - struct sun8i_a83t_mipi_csi2_dev *cdev = - (struct sun8i_a83t_mipi_csi2_dev *)dev_id; - struct regmap *regmap = cdev->regmap; - u32 status; - - WARN_ONCE(1, MODULE_NAME - ": Unsolicited interrupt, an error likely occurred!\n"); - - regmap_read(regmap, SUN8I_A83T_MIPI_CSI2_INT_STA0_REG, &status); - regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_INT_STA0_REG, status); - - regmap_read(regmap, SUN8I_A83T_MIPI_CSI2_INT_STA1_REG, &status); - regmap_write(regmap, SUN8I_A83T_MIPI_CSI2_INT_STA1_REG, status); - - regmap_read(regmap, SUN8I_A83T_MIPI_CSI2_INT_MSK0_REG, &status); - regmap_read(regmap, SUN8I_A83T_MIPI_CSI2_INT_MSK1_REG, &status); - - /* - * The interrupt can be used to catch transmission errors. - * However, we currently lack plumbing for reporting that to the - * A31 CSI controller driver. - */ - - return IRQ_HANDLED; -} - static void sun8i_a83t_mipi_csi2_init(struct sun8i_a83t_mipi_csi2_dev *cdev) { struct regmap *regmap = cdev->regmap; @@ -587,7 +559,6 @@ static int sun8i_a83t_mipi_csi2_resource_request(struct sun8i_a83t_mipi_csi2_dev { struct resource *res; void __iomem *io_base; - int irq; int ret; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -626,17 +597,6 @@ static int sun8i_a83t_mipi_csi2_resource_request(struct sun8i_a83t_mipi_csi2_dev return PTR_ERR(cdev->reset); } - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return -ENXIO; - - ret = devm_request_irq(&pdev->dev, irq, sun8i_a83t_mipi_csi2_isr, 0, - MODULE_NAME, cdev); - if (ret) { - dev_err(&pdev->dev, "failed to request MIPI CSI-2 IRQ\n"); - return ret; - } - ret = sun8i_a83t_dphy_register(cdev); if (ret) { dev_err(&pdev->dev, "failed to init MIPI D-PHY\n");