From patchwork Mon Jul 9 13:48:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Heiko_St=C3=BCbner?= X-Patchwork-Id: 10514655 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 44A1760318 for ; Mon, 9 Jul 2018 13:49:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3152328AE0 for ; Mon, 9 Jul 2018 13:49:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 251CD28B0C; Mon, 9 Jul 2018 13:49:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 9B7CD28AE0 for ; Mon, 9 Jul 2018 13:49:22 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 259176E4C9; Mon, 9 Jul 2018 13:48:57 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from gloria.sntech.de (gloria.sntech.de [185.11.138.130]) by gabe.freedesktop.org (Postfix) with ESMTPS id A273B6E4BC for ; Mon, 9 Jul 2018 13:48:46 +0000 (UTC) Received: from wd0142.dip.tu-dresden.de ([141.76.108.142] helo=phil.dip.tu-dresden.de) by gloria.sntech.de with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.89) (envelope-from ) id 1fcWWy-0005PY-MS; Mon, 09 Jul 2018 15:48:44 +0200 From: Heiko Stuebner To: dri-devel@lists.freedesktop.org Subject: [PATCH v3 8/8] drm/rockchip: dsi: add dual mipi support Date: Mon, 9 Jul 2018 15:48:34 +0200 Message-Id: <20180709134834.11035-9-heiko@sntech.de> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180709134834.11035-1-heiko@sntech.de> References: <20180709134834.11035-1-heiko@sntech.de> X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, briannorris@chromium.org, hoegsberg@gmail.com, philippe.cornu@st.com, yannick.fertre@st.com, linux-rockchip@lists.infradead.org, nickey.yang@rock-chips.com, robh+dt@kernel.org, thierry.reding@gmail.com, laurent.pinchart@ideasonboard.com, mka@chromium.org MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Add the Rockchip-sepcific dual-dsi setup and hook it into the VOP as well. As described in the general dual-dsi devicetree binding, the panel should define two input ports and point each of them to one of the used dsi- controllers, as well as declare one of them as clock-master. This is used to determine the dual-dsi state and get access to both controller instances. Signed-off-by: Heiko Stuebner --- .../gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 76 ++++++++++++++++++- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 3 + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 4 + drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 1 + 5 files changed, 83 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index 46e159524ec8..483b753ad5a2 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -218,6 +218,10 @@ struct dw_mipi_dsi_rockchip { struct clk *grf_clk; struct clk *phy_cfg_clk; + /* dual-channel */ + bool is_slave; + struct dw_mipi_dsi_rockchip *slave; + unsigned int lane_mbps; /* per lane */ u16 input_div; u16 feedback_div; @@ -602,6 +606,8 @@ dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder, } s->output_type = DRM_MODE_CONNECTOR_DSI; + if (dsi->slave) + s->output_flags = ROCKCHIP_OUTPUT_DSI_DUAL; return 0; } @@ -617,6 +623,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) return; pm_runtime_get_sync(dsi->dev); + if (dsi->slave) + pm_runtime_get_sync(dsi->slave->dev); /* * For the RK3399, the clk of grf must be enabled before writing grf @@ -630,6 +638,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) } dw_mipi_dsi_rockchip_config(dsi, mux); + if (dsi->slave) + dw_mipi_dsi_rockchip_config(dsi->slave, mux); clk_disable_unprepare(dsi->grf_clk); } @@ -638,6 +648,8 @@ static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder) { struct dw_mipi_dsi_rockchip *dsi = to_dsi(encoder); + if (dsi->slave) + pm_runtime_put(dsi->slave->dev); pm_runtime_put(dsi->dev); } @@ -679,25 +691,82 @@ static int dw_mipi_dsi_rockchip_bind(struct device *dev, { struct dw_mipi_dsi_rockchip *dsi = dev_get_drvdata(dev); struct drm_device *drm_dev = data; + struct device_node *second_np; struct drm_bridge *bridge; struct drm_panel *panel; + bool master1, master2; int ret; /* - * Handle probe-deferrals due to missing display. + * At this point both DSIs (if in use) should have probed and found + * any connected displays or bridges. + * This also takes care of handling possible probe-deferrals. */ ret = drm_of_find_panel_or_bridge(dsi->dev->of_node, 1, 0, &panel, &bridge); if (ret) return ret; + second_np = of_mipi_dsi_find_second_host(dsi->dev->of_node, 1, 0); + if (IS_ERR(second_np)) + return PTR_ERR(second_np); + /* * We know that there is a panel present but it may not have * finished attaching to the host. Defer in that case. + * Single-DSI case. */ - if (!dw_mipi_dsi_device_attached(dsi->dmd)) + if (!second_np && !dw_mipi_dsi_device_attached(dsi->dmd)) return -EPROBE_DEFER; + if (second_np) { + struct platform_device *pdev; + + master1 = of_property_read_bool(dsi->dev->of_node, + "clock-master"); + master2 = of_property_read_bool(second_np, "clock-master"); + + if (master1 && master2) { + DRM_DEV_ERROR(dsi->dev, "only one clock-master allowed\n"); + of_node_put(second_np); + return -EINVAL; + } + + if (!master1 && !master2) { + DRM_DEV_ERROR(dsi->dev, "no clock-master defined\n"); + of_node_put(second_np); + return -EINVAL; + } + + /* we are the slave in dual-DSI */ + if (!master1) { + dsi->is_slave = true; + of_node_put(second_np); + return 0; + } + + /* make sure, panel is attached to the master */ + if (!dw_mipi_dsi_device_attached(dsi->dmd)) + return -EPROBE_DEFER; + + pdev = of_find_device_by_node(second_np); + if (!pdev) { + DRM_DEV_ERROR(dev, "could not find slave controller\n"); + return -ENODEV; + } + + dsi->slave = platform_get_drvdata(pdev); + if (!dsi->slave) { + DRM_DEV_ERROR(dev, "could not get slaves platform-data\n"); + return -ENODEV; + } + + dsi->slave->is_slave = true; + dw_mipi_dsi_set_slave(dsi->dmd, dsi->slave->dmd); + + of_node_put(second_np); + } + ret = clk_prepare_enable(dsi->pllref_clk); if (ret) { DRM_DEV_ERROR(dev, "Failed to enable pllref_clk: %d\n", ret); @@ -725,6 +794,9 @@ static void dw_mipi_dsi_rockchip_unbind(struct device *dev, { struct dw_mipi_dsi_rockchip *dsi = dev_get_drvdata(dev); + if (dsi->is_slave) + return; + dw_mipi_dsi_unbind(dsi->dmd); clk_disable_unprepare(dsi->pllref_clk); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 96bb4ca8febf..2e6d2d4d1b65 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -37,6 +37,7 @@ struct rockchip_crtc_state { int output_type; int output_mode; int output_bpc; + int output_flags; }; #define to_rockchip_crtc_state(s) \ container_of(s, struct rockchip_crtc_state, base) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index effecbed2d11..313b163a346b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -916,6 +916,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, pin_pol |= (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) ? BIT(VSYNC_POSITIVE) : 0; VOP_REG_SET(vop, output, pin_pol, pin_pol); + VOP_REG_SET(vop, output, mipi_dual_channel_en, 0); switch (s->output_type) { case DRM_MODE_CONNECTOR_LVDS: @@ -933,6 +934,8 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, case DRM_MODE_CONNECTOR_DSI: VOP_REG_SET(vop, output, mipi_pin_pol, pin_pol); VOP_REG_SET(vop, output, mipi_en, 1); + VOP_REG_SET(vop, output, mipi_dual_channel_en, + !!(s->output_flags & ROCKCHIP_OUTPUT_DSI_DUAL)); break; case DRM_MODE_CONNECTOR_DisplayPort: pin_pol &= ~BIT(DCLK_INVERT); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index fcb91041a666..361e4c7d225c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -60,6 +60,7 @@ struct vop_output { struct vop_reg edp_en; struct vop_reg hdmi_en; struct vop_reg mipi_en; + struct vop_reg mipi_dual_channel_en; struct vop_reg rgb_en; }; @@ -213,6 +214,9 @@ struct vop_data { /* for use special outface */ #define ROCKCHIP_OUT_MODE_AAAA 15 +/* output flags */ +#define ROCKCHIP_OUTPUT_DSI_DUAL BIT(0) + enum alpha_mode { ALPHA_STRAIGHT, ALPHA_INVERSE, diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 08023d3ecb76..56d83f1c2599 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -421,6 +421,7 @@ static const struct vop_output rk3399_output = { .hdmi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 13), .edp_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 14), .mipi_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 15), + .mipi_dual_channel_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 3), }; static const struct vop_data rk3399_vop_big = {