All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marek Szyprowski <m.szyprowski@samsung.com>
To: Jagan Teki <jagan@amarulasolutions.com>,
	Inki Dae <inki.dae@samsung.com>,
	Neil Armstrong <narmstrong@baylibre.com>,
	Robert Foss <robert.foss@linaro.org>,
	Laurent Pinchart <Laurent.pinchart@ideasonboard.com>,
	Sam Ravnborg <sam@ravnborg.org>,
	Andrzej Hajda <andrzej.hajda@intel.com>
Cc: linux-amarula@amarulasolutions.com, dri-devel@lists.freedesktop.org
Subject: Re: [PATCH 1/2] drm: exynos: dsi: Convert to bridge driver
Date: Mon, 22 Nov 2021 15:15:47 +0100	[thread overview]
Message-ID: <5e173bc6-a320-42ec-79de-0ea4c3c2b480@samsung.com> (raw)
In-Reply-To: <20211122070633.89219-2-jagan@amarulasolutions.com>

On 22.11.2021 08:06, Jagan Teki wrote:
> 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 requires
> DSI Host to handle drm bridge functionalities in order to DSI
> Host to Interface bridge.
>
> This patch convert the existing to a drm bridge driver with a
> built-in encoder support for compatibility with existing
> component drivers.
>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
> Note:
> Hi Marek Szyprowski,
>
> Please test this on Panel and Bridge hardware.

I don't have good news, t crashes:

[drm] Exynos DRM: using 13800000.decon device for DMA mapping operations
exynos-drm exynos-drm: bound 13800000.decon (ops decon_component_ops)
exynos-drm exynos-drm: bound 13880000.decon (ops decon_component_ops)
exynos-drm exynos-drm: bound 13930000.mic (ops exynos_mic_component_ops)
[drm:drm_bridge_attach] *ERROR* failed to attach bridge 
/soc@0/dsi@13900000 to encoder TMDS-67: -22
exynos-drm exynos-drm: failed to bind 13900000.dsi (ops 
exynos_dsi_component_ops): -22
Internal error: synchronous external abort: 96000210 [#1] PREEMPT SMP
Modules linked in:
CPU: 2 PID: 74 Comm: kworker/u16:1 Not tainted 5.16.0-rc1+ #4141
Hardware name: Samsung TM2E board (DT)
Workqueue: events_unbound deferred_probe_work_func
pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
pc : decon_atomic_disable+0x58/0xd4
lr : decon_atomic_disable+0x28/0xd4
sp : ffff80001390b940
x29: ffff80001390b940 x28: ffff80001259a000 x27: ffff000027f39e80
input: stmfts as 
/devices/platform/soc@0/14ed0000.hsi2c/i2c-3/3-0049/input/input0
x26: 00000000ffffffea x25: ffff000025a40280 x24: 0000000000000001
x23: ffff800011b55f98 x22: ffff0000315dc000 x21: ffff00002695d100
x20: ffff000027e7a080 x19: ffff0000315e6000 x18: 0000000000000000
x17: 645f736f6e797865 x16: 2073706f28206973 x15: 0000000000028ee0
x14: 0000000000000028 x13: 0000000000000001 x12: 0000000000000040
x11: ffff000023c18920 x10: ffff000023c18922 x9 : ffff8000126352f0
x8 : ffff000023c00270 x7 : 0000000000000000 x6 : ffff000023c00268
x5 : ffff000027e7a3a0 x4 : 0000000000000001 x3 : ffff000027e7a080
x2 : 0000000000000024 x1 : ffff800013bc8024 x0 : ffff0000246117c0
Call trace:
  decon_atomic_disable+0x58/0xd4
  decon_unbind+0x1c/0x3c
  component_unbind+0x38/0x60
  component_bind_all+0x16c/0x25c
  exynos_drm_bind+0x104/0x1bc
  try_to_bring_up_master+0x164/0x1d0
  __component_add+0xa8/0x174
  component_add+0x14/0x20
  hdmi_probe+0x438/0x710
  platform_probe+0x68/0xe0
  really_probe.part.0+0x9c/0x31c
  __driver_probe_device+0x98/0x144
  driver_probe_device+0xc8/0x160
  __device_attach_driver+0xb8/0x120
  bus_for_each_drv+0x78/0xd0
  __device_attach+0xd8/0x180
  device_initial_probe+0x14/0x20
  bus_probe_device+0x9c/0xa4
  deferred_probe_work_func+0x88/0xc4
  process_one_work+0x288/0x6f0
  worker_thread+0x74/0x470
  kthread+0x188/0x194
  ret_from_fork+0x10/0x20
Code: 11002042 f9481c61 531e7442 8b020021 (88dffc21)
---[ end trace d73aff585b108954 ]---
Kernel panic - not syncing: synchronous external abort: Fatal exception
SMP: stopping secondary CPUs
Kernel Offset: disabled
CPU features: 0x2,300071c2,00000846
Memory Limit: none
---[ end Kernel panic - not syncing: synchronous external abort: Fatal 
exception ]---

I will try to debug it a bit more once I find some spare time. I've 
applied only the first patch.

>   drivers/gpu/drm/exynos/exynos_drm_dsi.c | 73 +++++++++++++++++--------
>   1 file changed, 51 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> index 8d137857818c..174590f543c3 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -257,6 +257,7 @@ struct exynos_dsi {
>   	struct drm_connector connector;
>   	struct drm_panel *panel;
>   	struct list_head bridge_chain;
> +	struct drm_bridge bridge;
>   	struct drm_bridge *out_bridge;
>   	struct device *dev;
>   
> @@ -287,9 +288,9 @@ struct exynos_dsi {
>   #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
>   #define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
>   
> -static inline struct exynos_dsi *encoder_to_dsi(struct drm_encoder *e)
> +static inline struct exynos_dsi *bridge_to_dsi(struct drm_bridge *b)
>   {
> -	return container_of(e, struct exynos_dsi, encoder);
> +	return container_of(b, struct exynos_dsi, bridge);
>   }
>   
>   enum reg_idx {
> @@ -1374,9 +1375,10 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
>   	}
>   }
>   
> -static void exynos_dsi_enable(struct drm_encoder *encoder)
> +static void exynos_dsi_atomic_enable(struct drm_bridge *bridge,
> +				     struct drm_bridge_state *old_bridge_state)
>   {
> -	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
> +	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
>   	struct drm_bridge *iter;
>   	int ret;
>   
> @@ -1399,7 +1401,8 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
>   		list_for_each_entry_reverse(iter, &dsi->bridge_chain,
>   					    chain_node) {
>   			if (iter->funcs->pre_enable)
> -				iter->funcs->pre_enable(iter);
> +				iter->funcs->atomic_pre_enable(iter,
> +							       old_bridge_state);
>   		}
>   	}
>   
> @@ -1413,7 +1416,7 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
>   	} else {
>   		list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
>   			if (iter->funcs->enable)
> -				iter->funcs->enable(iter);
> +				iter->funcs->atomic_enable(iter, old_bridge_state);
>   		}
>   	}
>   
> @@ -1429,9 +1432,10 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
>   	pm_runtime_put(dsi->dev);
>   }
>   
> -static void exynos_dsi_disable(struct drm_encoder *encoder)
> +static void exynos_dsi_atomic_disable(struct drm_bridge *bridge,
> +				      struct drm_bridge_state *old_bridge_state)
>   {
> -	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
> +	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
>   	struct drm_bridge *iter;
>   
>   	if (!(dsi->state & DSIM_STATE_ENABLED))
> @@ -1443,7 +1447,7 @@ static void exynos_dsi_disable(struct drm_encoder *encoder)
>   
>   	list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
>   		if (iter->funcs->disable)
> -			iter->funcs->disable(iter);
> +			iter->funcs->atomic_disable(iter, old_bridge_state);
>   	}
>   
>   	exynos_dsi_set_display_enable(dsi, false);
> @@ -1451,7 +1455,7 @@ static void exynos_dsi_disable(struct drm_encoder *encoder)
>   
>   	list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
>   		if (iter->funcs->post_disable)
> -			iter->funcs->post_disable(iter);
> +			iter->funcs->atomic_post_disable(iter, old_bridge_state);
>   	}
>   
>   	dsi->state &= ~DSIM_STATE_ENABLED;
> @@ -1494,9 +1498,9 @@ static const struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs
>   	.get_modes = exynos_dsi_get_modes,
>   };
>   
> -static int exynos_dsi_create_connector(struct drm_encoder *encoder)
> +static int exynos_dsi_create_connector(struct exynos_dsi *dsi)
>   {
> -	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
> +	struct drm_encoder *encoder = &dsi->encoder;
>   	struct drm_connector *connector = &dsi->connector;
>   	struct drm_device *drm = encoder->dev;
>   	int ret;
> @@ -1522,9 +1526,21 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder)
>   	return 0;
>   }
>   
> -static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = {
> -	.enable = exynos_dsi_enable,
> -	.disable = exynos_dsi_disable,
> +static int exynos_dsi_attach(struct drm_bridge *bridge,
> +			     enum drm_bridge_attach_flags flags)
> +{
> +	struct exynos_dsi *dsi = bridge_to_dsi(bridge);
> +
> +	return drm_bridge_attach(bridge->encoder, dsi->out_bridge, NULL, 0);
> +}
> +
> +static const struct drm_bridge_funcs exynos_dsi_bridge_funcs = {
> +	.atomic_duplicate_state	= drm_atomic_helper_bridge_duplicate_state,
> +	.atomic_destroy_state	= drm_atomic_helper_bridge_destroy_state,
> +	.atomic_reset		= drm_atomic_helper_bridge_reset,
> +	.atomic_enable		= exynos_dsi_atomic_enable,
> +	.atomic_disable		= exynos_dsi_atomic_disable,
> +	.attach			= exynos_dsi_attach,
>   };
>   
>   MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
> @@ -1543,7 +1559,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
>   		dsi->out_bridge = out_bridge;
>   		list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain);
>   	} else {
> -		int ret = exynos_dsi_create_connector(encoder);
> +		int ret = exynos_dsi_create_connector(dsi);
>   
>   		if (ret) {
>   			DRM_DEV_ERROR(dsi->dev,
> @@ -1596,7 +1612,7 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
>   
>   	if (dsi->panel) {
>   		mutex_lock(&drm->mode_config.mutex);
> -		exynos_dsi_disable(&dsi->encoder);
> +		exynos_dsi_atomic_disable(&dsi->bridge, NULL);
>   		dsi->panel = NULL;
>   		dsi->connector.status = connector_status_disconnected;
>   		mutex_unlock(&drm->mode_config.mutex);
> @@ -1702,12 +1718,16 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
>   
>   	drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
>   
> -	drm_encoder_helper_add(encoder, &exynos_dsi_encoder_helper_funcs);
> -
>   	ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD);
>   	if (ret < 0)
>   		return ret;
>   
> +	ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL, 0);
> +	if (ret) {
> +		drm_encoder_cleanup(&dsi->encoder);
> +		return ret;
> +	}
> +
>   	in_bridge_node = of_graph_get_remote_node(dev->of_node, DSI_PORT_IN, 0);
>   	if (in_bridge_node) {
>   		in_bridge = of_drm_find_bridge(in_bridge_node);
> @@ -1723,10 +1743,9 @@ static void exynos_dsi_unbind(struct device *dev, struct device *master,
>   				void *data)
>   {
>   	struct exynos_dsi *dsi = dev_get_drvdata(dev);
> -	struct drm_encoder *encoder = &dsi->encoder;
> -
> -	exynos_dsi_disable(encoder);
>   
> +	exynos_dsi_atomic_disable(&dsi->bridge, NULL);
> +	drm_encoder_cleanup(&dsi->encoder);
>   	mipi_dsi_host_unregister(&dsi->dsi_host);
>   }
>   
> @@ -1819,6 +1838,12 @@ static int exynos_dsi_probe(struct platform_device *pdev)
>   
>   	pm_runtime_enable(dev);
>   
> +	dsi->bridge.funcs = &exynos_dsi_bridge_funcs;
> +	dsi->bridge.of_node = dev->of_node;
> +	dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
> +
> +	drm_bridge_add(&dsi->bridge);
> +
>   	ret = component_add(dev, &exynos_dsi_component_ops);
>   	if (ret)
>   		goto err_disable_runtime;
> @@ -1833,6 +1858,10 @@ static int exynos_dsi_probe(struct platform_device *pdev)
>   
>   static int exynos_dsi_remove(struct platform_device *pdev)
>   {
> +	struct exynos_dsi *dsi = platform_get_drvdata(pdev);
> +
> +	drm_bridge_remove(&dsi->bridge);
> +
>   	pm_runtime_disable(&pdev->dev);
>   
>   	component_del(&pdev->dev, &exynos_dsi_component_ops);

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


  parent reply	other threads:[~2021-11-22 14:15 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-22  7:06 [PATCH 0/2] drm: exynos: dsi: Convert drm bridge Jagan Teki
2021-11-22  7:06 ` [PATCH 1/2] drm: exynos: dsi: Convert to bridge driver Jagan Teki
2021-11-22 13:59   ` Jagan Teki
2021-11-22 14:15   ` Marek Szyprowski [this message]
2021-11-22 14:21     ` Jagan Teki
2021-11-22 14:29       ` Jagan Teki
2021-11-22 14:55         ` Jagan Teki
2021-11-22 15:07           ` Marek Szyprowski
2021-11-22 16:04             ` Marek Szyprowski
2021-11-24  5:32               ` Jagan Teki
2021-11-24 14:53                 ` Marek Szyprowski
2021-11-24 15:00                   ` Jagan Teki
2022-01-10 11:17               ` Jagan Teki
2022-01-10 15:32                 ` Robert Foss
2022-01-10 15:34                   ` Jagan Teki
2022-01-10 15:40                     ` Robert Foss
2022-01-11 18:58                       ` Jagan Teki
2021-11-22 14:40       ` Fabio Estevam
2021-11-22 14:46         ` Marek Szyprowski
2021-11-22 14:41       ` Marek Szyprowski
2021-11-22  7:06 ` [PATCH 2/2] drm: exynos: dsi: Add mode_set function Jagan Teki
2022-01-04 15:07   ` Robert Foss

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=5e173bc6-a320-42ec-79de-0ea4c3c2b480@samsung.com \
    --to=m.szyprowski@samsung.com \
    --cc=Laurent.pinchart@ideasonboard.com \
    --cc=andrzej.hajda@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=inki.dae@samsung.com \
    --cc=jagan@amarulasolutions.com \
    --cc=linux-amarula@amarulasolutions.com \
    --cc=narmstrong@baylibre.com \
    --cc=robert.foss@linaro.org \
    --cc=sam@ravnborg.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.