From patchwork Fri Dec 10 11:17:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 1803 Return-Path: X-Original-To: linux-amarula@patchwork.amarulasolutions.com Delivered-To: linux-amarula@patchwork.amarulasolutions.com Received: from mail-pg1-f199.google.com (mail-pg1-f199.google.com [209.85.215.199]) by ganimede.amarulasolutions.com (Postfix) with ESMTPS id 8C2083F15A for ; Fri, 10 Dec 2021 12:17:42 +0100 (CET) Received: by mail-pg1-f199.google.com with SMTP id i15-20020a63e90f000000b0033a835b882csf104890pgh.13 for ; Fri, 10 Dec 2021 03:17:42 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1639135061; cv=pass; d=google.com; s=arc-20160816; b=R6uuc5e4IaOnwJOMvTrE7h/3NJM254dBPsU0bDsa7tsOO831wpmXbxxSBogkleW9Bh YG2n2oyG+rLYvsmuHiHcQN8iFCKS6rOetOJPnajQPeC82PuJmZLoahiiwOkvlNnCXjrZ +v0Ecd+uQoA+bePinzPuAwMwy8q7g0tz8ivg1K8igHzvNhhJKzRqZxXT6WnxEVWIbSO2 axF0SgAFd1SiirXwoo0WMkOWh4BMoKOxN2bNwKRGBaDSQrI3rZ4c2O4qzpuZ2X401RiH KmGKkD911/ljupdy/fYgxL1v7Cxf8QY/2NEYTFilMprNiOLNwAyjTDFsMpfrnC/lGBGS ITDQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-archive:list-help:list-post:list-id :mailing-list:precedence:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=bbRBAwKJfP6L6vFW6x+k1N86Sjs3mZ891ax6ADL+gy4=; b=E9gfnf3jlmO8hsi9zYj/9WC0JY98PQ+l4Lk/UxBjQtJVATp/qJ6vx03LH/dkTp6ftB oqO6TRJIP/qrtCl+cXDwG9vwBai6TYyhlbn8ViQw9Q/IMWwHYDQzXErPQ3gh9fW9Z/Kz +Q8BRUIOb8gOM2kulwTnTsidpkQ349+FJmTk1AWLT7LBl6UIlc1OhlfeCV07JTG6Y/jt sSNZygHp3x8hqIGFVqsT7tuRQN9b4Ap1WCAuhoVZb6nopiA3kvOYW2HIJPM/6OqPWAJ1 8ttZpAceBaULp6LSgGiDNEjG5sS5xgScef9yATj0t5fmjfWaxlTDYuUcG4D3Lb8SYdLj f/3w== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=o9ENum0+; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amarulasolutions.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-unsubscribe; bh=bbRBAwKJfP6L6vFW6x+k1N86Sjs3mZ891ax6ADL+gy4=; b=MFB3nOXF+mBN4hbTnRw6BVY89bqp2dB0fGtShP5+igPHkc20FPN9ks95UeII+KxY5o EKJKbniBk40b06zhkKL/1wmVhp/b2oteFCqO5u8S8/w0AhQHX2wX6XhEzlLbQjQO71mJ 8ldtzvI0xZVdj/flIFGLoS5j63O6+55K5+TL0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-spam-checked-in-group:list-post:list-help:list-archive :list-unsubscribe; bh=bbRBAwKJfP6L6vFW6x+k1N86Sjs3mZ891ax6ADL+gy4=; b=75shaaMqyMZtadiJmInxxIyvhakaYEYuw9T+SC4droA0UBZBZ50faLtx2Z+vpEHxZU Hu/P34CAvF5xwWJR1SRDJrbKr4iB+dZklMzwqeVWVpYkRry623ZbyuWgJCK4/OU55H8n TthAipxfHsQuxzp+FbWoCBH+sNqp8Lkj/Yaouk1bzl/ApjJMPfFncmNBonhrtTKO3dGW kXMwh2vKgPItcForq8TDGEO/yOMS4mxTrsXRMCW304bJJtqfbDQaFzXcQExUxY6Se9Bq aownxSxjvbJJbyROWkTbvmR2ov5KDa1yNEqpebet5jQBRsV18LIUkAmrOEQIneupzUR6 sNOA== X-Gm-Message-State: AOAM531/udpzh/bXfmmxLUChIVFxT6OvuaSXS23MSd+TRYt3y77cU6xg iOaWjVST18a/Kq5f6xNdLay2g7lU X-Google-Smtp-Source: ABdhPJyK5/+wEW58ob7f3zaN35HP1kabPblhTjRxGR40bq3mB/ypRVGwRxmkLeMYz2TdlEBFhpBa/g== X-Received: by 2002:a63:3c6:: with SMTP id 189mr32953848pgd.406.1639135061411; Fri, 10 Dec 2021 03:17:41 -0800 (PST) X-BeenThere: linux-amarula@amarulasolutions.com Received: by 2002:a05:6a00:a81:: with SMTP id b1ls3304403pfl.3.gmail; Fri, 10 Dec 2021 03:17:40 -0800 (PST) X-Received: by 2002:a63:124a:: with SMTP id 10mr4650533pgs.154.1639135060647; Fri, 10 Dec 2021 03:17:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1639135060; cv=none; d=google.com; s=arc-20160816; b=s7uyXlIMolseaGU0c2j9ibzzNXEwoR1WZ7FJHqJM/G7Hz7TWMXXb8jlQn4lcGMJE1f VXwsVJs7NCQh7VZP8KKXGquAy1LmEl7S7o1hQ+C3k1gFi0n1L7euql1RUtmpjSaY3e2s AzkA15fvUmyk8xaWL1dOTUMPcAH86yQS8MFqtT0rsUC4lT68mQPP+FBFCJmc/9k8C4BL 1moB0kod4J+Oj+I21y77TVTNzZCaqZM7nP7cTu6DDgMT2dmeBhXTnBRPm+kkI/nH+zTY ESWwxOT2fcCjP4AAJ6/5a0jyTd4CcpL+35ucku/uEn054I1HF/zTI05dZ4Oal3hpKoTT VUVw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=1kZgbgJmrlxw0BX7jCIeMycv2sDZ8RydaNArchhpYlI=; b=SIlDbGXjcXYKji0SK5zILnf8j8aKyGNqF2zirrbD1ACA7CkOmQdLizLN3M3orr2iNS DJ9iAMYPwn5t/3ulwsKXkuVx+qo3cEqwHGWIh2vIdzJoEXGHAusy0VKl0YqGrcUgaoVn p/UAxdGPcYccWFBkIPOUNavF4XH+YZgnlbGtoUC22/Ib0df186jB4w20oJMD+9lwvYeh 1D+Lbm+1ynBkgJGPxIIXr8IbdvSS/4sr7orn1VtVp/Et5/+DpnTo6KukyMKUaewEWLZm sOITf/ZydRUrPbgZRs03p5vA00UZcrswFAN303X+ZbMJ1lVDxRXS68iLGlvQBu4+eTig fY3w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=o9ENum0+; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com Received: from mail-sor-f41.google.com (mail-sor-f41.google.com. [209.85.220.41]) by mx.google.com with SMTPS id h7sor2343860pjj.14.2021.12.10.03.17.40 for (Google Transport Security); Fri, 10 Dec 2021 03:17:40 -0800 (PST) Received-SPF: pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.41 as permitted sender) client-ip=209.85.220.41; X-Received: by 2002:a17:90a:ab17:: with SMTP id m23mr22947589pjq.194.1639135060298; Fri, 10 Dec 2021 03:17:40 -0800 (PST) Received: from localhost.localdomain ([2405:201:c00a:a0a9:c40f:36d4:b45d:731]) by smtp.gmail.com with ESMTPSA id qe12sm13125607pjb.29.2021.12.10.03.17.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Dec 2021 03:17:39 -0800 (PST) From: Jagan Teki To: Maxime Ripard , Chen-Yu Tsai , Laurent Pinchart , Neil Armstrong , Robert Foss , Sam Ravnborg Cc: dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@googlegroups.com, linux-amarula@amarulasolutions.com, Jagan Teki Subject: [PATCH v6 3/6] drm: sun4i: dsi: Add bridge support Date: Fri, 10 Dec 2021 16:47:08 +0530 Message-Id: <20211210111711.2072660-4-jagan@amarulasolutions.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211210111711.2072660-1-jagan@amarulasolutions.com> References: <20211210111711.2072660-1-jagan@amarulasolutions.com> MIME-Version: 1.0 X-Original-Sender: jagan@amarulasolutions.com X-Original-Authentication-Results: mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=o9ENum0+; spf=pass (google.com: domain of jagan@amarulasolutions.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=jagan@amarulasolutions.com Content-Type: text/plain; charset="UTF-8" Precedence: list Mailing-list: list linux-amarula@amarulasolutions.com; contact linux-amarula+owners@amarulasolutions.com List-ID: X-Spam-Checked-In-Group: linux-amarula@amarulasolutions.com X-Google-Group-Id: 476853432473 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Some display panels would come up with a non-DSI output, those can have an option to connect the DSI host by means of interface bridge converter. This DSI to non-DSI interface bridge converter would require DSI Host to handle drm bridge functionalities in order to communicate interface bridge. This patch adds support for bridge functionalities in Allwinner DSI controller. Supporting down-stream bridge makes few changes in the driver. - It drops drm_connector and related operations as drm_bridge_attach creates connector during attachment. - It drop panel pointer and iterate the bridge, so-that it can operate the normal bridge and panel_bridge in constitutive callbacks. - It uses devm_drm_of_get_bridge for panel or bridge lookup. It uses port 0 and endpoint 0 to support I2C-based bridges eventhough the usual Allwinner DSI OF graph doesn't require this for panel and non-I2C based downstream bridges. Signed-off-by: Jagan Teki --- Changes for v6: - support donwstream bridge - drop bridge conversion - devm_drm_of_get_bridge() require child lookup https://patchwork.kernel.org/project/dri-devel/cover/20211207054747.461029-1-jagan@amarulasolutions.com/ Changes for v5: - add atomic APIs - find host and device variant DSI devices. Changes for v4, v3: - none drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 83 ++++++++++---------------- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h | 9 +-- 2 files changed, 33 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c index 9cf91dcac3f2..f1d612bf1a0b 100644 --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -720,6 +721,7 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder) struct mipi_dsi_device *device = dsi->device; union phy_configure_opts opts = { }; struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy; + struct drm_bridge *iter; u16 delay; int err; @@ -769,8 +771,10 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder) phy_configure(dsi->dphy, &opts); phy_power_on(dsi->dphy); - if (dsi->panel) - drm_panel_prepare(dsi->panel); + list_for_each_entry(iter, &dsi->bridge_chain, chain_node) { + if (iter->funcs->pre_enable) + iter->funcs->pre_enable(iter); + } /* * FIXME: This should be moved after the switch to HS mode. @@ -784,8 +788,10 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder) * ordering on the panels I've tested it with, so I guess this * will do for now, until that IP is better understood. */ - if (dsi->panel) - drm_panel_enable(dsi->panel); + list_for_each_entry(iter, &dsi->bridge_chain, chain_node) { + if (iter->funcs->enable) + iter->funcs->enable(iter); + } sun6i_dsi_start(dsi, DSI_START_HSC); @@ -797,12 +803,16 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder) static void sun6i_dsi_encoder_disable(struct drm_encoder *encoder) { struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder); + struct drm_bridge *iter; DRM_DEBUG_DRIVER("Disabling DSI output\n"); - if (dsi->panel) { - drm_panel_disable(dsi->panel); - drm_panel_unprepare(dsi->panel); + list_for_each_entry(iter, &dsi->bridge_chain, chain_node) { + if (iter->funcs->disable) + iter->funcs->disable(iter); + + if (iter->funcs->post_disable) + iter->funcs->post_disable(iter); } phy_power_off(dsi->dphy); @@ -813,35 +823,6 @@ static void sun6i_dsi_encoder_disable(struct drm_encoder *encoder) regulator_disable(dsi->regulator); } -static int sun6i_dsi_get_modes(struct drm_connector *connector) -{ - struct sun6i_dsi *dsi = connector_to_sun6i_dsi(connector); - - return drm_panel_get_modes(dsi->panel, connector); -} - -static const struct drm_connector_helper_funcs sun6i_dsi_connector_helper_funcs = { - .get_modes = sun6i_dsi_get_modes, -}; - -static enum drm_connector_status -sun6i_dsi_connector_detect(struct drm_connector *connector, bool force) -{ - struct sun6i_dsi *dsi = connector_to_sun6i_dsi(connector); - - return dsi->panel ? connector_status_connected : - connector_status_disconnected; -} - -static const struct drm_connector_funcs sun6i_dsi_connector_funcs = { - .detect = sun6i_dsi_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = drm_connector_cleanup, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - static const struct drm_encoder_helper_funcs sun6i_dsi_enc_helper_funcs = { .disable = sun6i_dsi_encoder_disable, .enable = sun6i_dsi_encoder_enable, @@ -976,22 +957,17 @@ static int sun6i_dsi_bind(struct device *dev, struct device *master, } dsi->encoder.possible_crtcs = BIT(0); - drm_connector_helper_add(&dsi->connector, - &sun6i_dsi_connector_helper_funcs); - ret = drm_connector_init(drm, &dsi->connector, - &sun6i_dsi_connector_funcs, - DRM_MODE_CONNECTOR_DSI); + ret = drm_bridge_attach(&dsi->encoder, dsi->next_bridge, NULL, 0); if (ret) { - dev_err(dsi->dev, - "Couldn't initialise the DSI connector\n"); - goto err_cleanup_connector; + dev_err(dsi->dev, "Couldn't attach drm bridge\n"); + goto err_cleanup_encoder; } - drm_connector_attach_encoder(&dsi->connector, &dsi->encoder); + list_splice_init(&dsi->encoder.bridge_chain, &dsi->bridge_chain); return 0; -err_cleanup_connector: +err_cleanup_encoder: drm_encoder_cleanup(&dsi->encoder); return ret; } @@ -1013,17 +989,18 @@ static int sun6i_dsi_attach(struct mipi_dsi_host *host, struct mipi_dsi_device *device) { struct sun6i_dsi *dsi = host_to_sun6i_dsi(host); - struct drm_panel *panel = of_drm_find_panel(device->dev.of_node); struct device *dev = dsi->dev; int ret; - if (IS_ERR(panel)) - return PTR_ERR(panel); + dsi->next_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0); + if (IS_ERR(dsi->next_bridge)) { + dev_err(dsi->dev, "Couldn't find the bridge\n"); + return PTR_ERR(dsi->next_bridge); + } - dsi->panel = panel; dsi->device = device; - dev_info(host->dev, "Attached device %s\n", device->name); + dev_info(host->dev, "Attached %s\n", device->name); ret = component_add(dev, &sun6i_dsi_ops); if (ret) { @@ -1040,7 +1017,7 @@ static int sun6i_dsi_detach(struct mipi_dsi_host *host, { struct sun6i_dsi *dsi = host_to_sun6i_dsi(host); - dsi->panel = NULL; + dsi->next_bridge = NULL; dsi->device = NULL; component_del(dsi->dev, &sun6i_dsi_ops); @@ -1118,6 +1095,8 @@ static int sun6i_dsi_probe(struct platform_device *pdev) dsi->host.ops = &sun6i_dsi_host_ops; dsi->host.dev = dev; + INIT_LIST_HEAD(&dsi->bridge_chain); + if (of_device_is_compatible(dev->of_node, "allwinner,sun6i-a31-mipi-dsi")) bus_clk_name = "bus"; diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h index 61e88ea6044d..96a219b9c275 100644 --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h @@ -16,7 +16,6 @@ #define SUN6I_DSI_TCON_DIV 4 struct sun6i_dsi { - struct drm_connector connector; struct drm_encoder encoder; struct mipi_dsi_host host; @@ -29,7 +28,8 @@ struct sun6i_dsi { struct device *dev; struct mipi_dsi_device *device; - struct drm_panel *panel; + struct drm_bridge *next_bridge; + struct list_head bridge_chain; }; static inline struct sun6i_dsi *host_to_sun6i_dsi(struct mipi_dsi_host *host) @@ -37,11 +37,6 @@ static inline struct sun6i_dsi *host_to_sun6i_dsi(struct mipi_dsi_host *host) return container_of(host, struct sun6i_dsi, host); }; -static inline struct sun6i_dsi *connector_to_sun6i_dsi(struct drm_connector *connector) -{ - return container_of(connector, struct sun6i_dsi, connector); -}; - static inline struct sun6i_dsi *encoder_to_sun6i_dsi(const struct drm_encoder *encoder) { return container_of(encoder, struct sun6i_dsi, encoder);