From: Jagan Teki <jagan@amarulasolutions.com>
To: Maxime Ripard <mripard@kernel.org>, Chen-Yu Tsai <wens@csie.org>,
Laurent Pinchart <Laurent.pinchart@ideasonboard.com>,
Neil Armstrong <narmstrong@baylibre.com>,
Robert Foss <robert.foss@linaro.org>,
Sam Ravnborg <sam@ravnborg.org>
Cc: dri-devel@lists.freedesktop.org,
linux-arm-kernel@lists.infradead.org,
linux-sunxi@googlegroups.com, linux-amarula@amarulasolutions.com,
Jagan Teki <jagan@amarulasolutions.com>
Subject: [PATCH v6 3/6] drm: sun4i: dsi: Add bridge support
Date: Fri, 10 Dec 2021 16:47:08 +0530 [thread overview]
Message-ID: <20211210111711.2072660-4-jagan@amarulasolutions.com> (raw)
In-Reply-To: <20211210111711.2072660-1-jagan@amarulasolutions.com>
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 <jagan@amarulasolutions.com>
---
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 <drm/drm_atomic_helper.h>
#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_of.h>
#include <drm/drm_panel.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
@@ -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);
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2021-12-10 11:19 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-10 11:17 [PATCH v6 0/6] drm: sun4i: dsi: Bridge support Jagan Teki
2021-12-10 11:17 ` [PATCH v6 1/6] drm: sun4i: dsi: Drop DRM bind race with bridge attach Jagan Teki
2021-12-13 17:02 ` Maxime Ripard
2022-01-17 15:42 ` Jagan Teki
2022-02-02 8:59 ` Maxime Ripard
2021-12-10 11:17 ` [PATCH v6 2/6] drm: sun4i: dsi: Add component only once DSI device attached Jagan Teki
2021-12-13 17:05 ` Maxime Ripard
2021-12-10 11:17 ` Jagan Teki [this message]
2021-12-13 17:17 ` [PATCH v6 3/6] drm: sun4i: dsi: Add bridge support Maxime Ripard
2022-01-17 15:38 ` Jagan Teki
2021-12-10 11:17 ` [DO NOT MERGE] [PATCH v6 4/6] ARM: dts: sun8i: bananapi-m2m: Enable iS070WV20-CT16 DSI Panel Jagan Teki
2021-12-10 11:17 ` [DO NOT MERGE] [PATCH v6 5/6] ARM: dts: sun8i: bananapi-m2m: Enable ICN6211 DSI Bridge Jagan Teki
2021-12-10 11:17 ` [DO NOT MERGE] [PATCH v6 6/6] ARM: dts: sun8i: bananapi-m2m: Enable DLPC3433 Bridge (I2C) Jagan Teki
2021-12-13 17:00 ` [PATCH v6 0/6] drm: sun4i: dsi: Bridge support Maxime Ripard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211210111711.2072660-4-jagan@amarulasolutions.com \
--to=jagan@amarulasolutions.com \
--cc=Laurent.pinchart@ideasonboard.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=linux-amarula@amarulasolutions.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-sunxi@googlegroups.com \
--cc=mripard@kernel.org \
--cc=narmstrong@baylibre.com \
--cc=robert.foss@linaro.org \
--cc=sam@ravnborg.org \
--cc=wens@csie.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox