dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] drm/fb-helper: Support deferred setup
@ 2016-06-03 16:11 Thierry Reding
  2016-06-03 16:11 ` [PATCH 2/4] drm/atmel-hlcdc: Remove custom FB helper " Thierry Reding
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Thierry Reding @ 2016-06-03 16:11 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Xinliang Liu, Chen Feng, Seung-Woo Kim, dri-devel, Kyungmin Park

From: Thierry Reding <treding@nvidia.com>

FB helper code falls back to a 1024x768 mode if no outputs are connected
or don't report back any modes upon initialization. This can be annoying
because outputs that are added to FB helper later on can't be used with
FB helper if they don't support a matching mode.

The fallback is in place because VGA connectors can happen to report an
unknown connection status even when they are in fact connected.

Some drivers have custom solutions in place to defer FB helper setup
until at least one output is connected. But the logic behind these
solutions is always the same and there is nothing driver-specific about
it, so a better alterative is to fix the FB helper core and add support
for all drivers automatically.

This patch adds support for deferred FB helper setup. It checks all the
connectors for their connection status, and if all of them report to be
disconnected marks the FB helper as needing deferred setup. Whet setup
is deferred, the FB helper core will automatically retry setup after a
hotplug event, and it will keep trying until it succeeds.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpu/drm/drm_fb_helper.c | 36 ++++++++++++++++++++++++++++++++++++
 include/drm/drm_fb_helper.h     | 21 +++++++++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 7c2eb75db60f..4f334f9cab28 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -442,6 +442,9 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
 	if (!drm_fbdev_emulation)
 		return -ENODEV;
 
+	if (fb_helper->deferred_setup)
+		return 0;
+
 	drm_modeset_lock_all(dev);
 	ret = restore_fbdev_mode(fb_helper);
 
@@ -1398,6 +1401,23 @@ unlock:
 }
 EXPORT_SYMBOL(drm_fb_helper_pan_display);
 
+static bool drm_fb_helper_maybe_connected(struct drm_fb_helper *helper)
+{
+	bool connected = false;
+	unsigned int i;
+
+	for (i = 0; i < helper->connector_count; i++) {
+		struct drm_fb_helper_connector *fb = helper->connector_info[i];
+
+		if (fb->connector->status != connector_status_disconnected) {
+			connected = true;
+			break;
+		}
+	}
+
+	return connected;
+}
+
 /*
  * Allocates the backing storage and sets up the fbdev info structure through
  * the ->fb_probe callback and then registers the fbdev and sets up the panic
@@ -1499,6 +1519,17 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 			sizes.fb_height = min_t(u32, desired_mode->vdisplay + y, sizes.fb_height);
 	}
 
+	/*
+	 * If everything's disconnected, there's no use in attempting to set
+	 * up fbdev.
+	 */
+	if (!drm_fb_helper_maybe_connected(fb_helper)) {
+		DRM_INFO("No outputs connected, deferring setup\n");
+		fb_helper->preferred_bpp = preferred_bpp;
+		fb_helper->deferred_setup = true;
+		return 0;
+	}
+
 	if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
 		/* hmm everyone went away - assume VGA cable just fell out
 		   and will come back later. */
@@ -1539,6 +1570,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 
 	list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
 
+	fb_helper->deferred_setup = false;
 	return 0;
 }
 
@@ -2237,6 +2269,10 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 	if (!drm_fbdev_emulation)
 		return 0;
 
+	if (fb_helper->deferred_setup)
+		return drm_fb_helper_initial_config(fb_helper,
+						    fb_helper->preferred_bpp);
+
 	mutex_lock(&fb_helper->dev->mode_config.mutex);
 	if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) {
 		fb_helper->delayed_hotplug = true;
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 5b4aa35026a3..25446690b2c1 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -214,6 +214,27 @@ struct drm_fb_helper {
 	bool delayed_hotplug;
 
 	/**
+	 * @deferred_setup:
+	 *
+	 * If no outputs are connected (disconnected or unknown) the FB helper
+	 * code will defer setup until at least one of the outputs shows up.
+	 * This field keeps track of the status so that setup can be retried
+	 * at every hotplug event until it succeeds eventually.
+	 */
+	bool deferred_setup;
+
+	/**
+	 * @preferred_bpp:
+	 *
+	 * Temporary storage for the driver's preferred BPP setting passed to
+	 * FB helper initialization. This needs to be tracked so that deferred
+	 * FB helper setup can pass this on.
+	 *
+	 * See also: @deferred_setup
+	 */
+	int preferred_bpp;
+
+	/**
 	 * @atomic:
 	 *
 	 * Use atomic updates for restore_fbdev_mode(), etc.  This defaults to
-- 
2.8.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/4] drm/atmel-hlcdc: Remove custom FB helper deferred setup
  2016-06-03 16:11 [PATCH 1/4] drm/fb-helper: Support deferred setup Thierry Reding
@ 2016-06-03 16:11 ` Thierry Reding
  2016-06-03 16:11 ` [PATCH 3/4] drm/exynos: " Thierry Reding
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Thierry Reding @ 2016-06-03 16:11 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Xinliang Liu, Chen Feng, Seung-Woo Kim, dri-devel, Kyungmin Park

From: Thierry Reding <treding@nvidia.com>

The FB helper core now supports deferred setup, so the driver's custom
implementation can be removed.

Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Compile-tested only.

 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 8ded7645747e..a8a855910885 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -431,15 +431,7 @@ static void atmel_hlcdc_fb_output_poll_changed(struct drm_device *dev)
 {
 	struct atmel_hlcdc_dc *dc = dev->dev_private;
 
-	if (dc->fbdev) {
-		drm_fbdev_cma_hotplug_event(dc->fbdev);
-	} else {
-		dc->fbdev = drm_fbdev_cma_init(dev, 24,
-				dev->mode_config.num_crtc,
-				dev->mode_config.num_connector);
-		if (IS_ERR(dc->fbdev))
-			dc->fbdev = NULL;
-	}
+	drm_fbdev_cma_hotplug_event(dc->fbdev);
 }
 
 struct atmel_hlcdc_dc_commit {
@@ -654,11 +646,23 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev)
 
 	drm_kms_helper_poll_init(dev);
 
-	/* force connectors detection */
-	drm_helper_hpd_irq_event(dev);
+	dc->fbdev = drm_fbdev_cma_init(dev, 24, dev->mode_config.num_crtc,
+				       dev->mode_config.num_connector);
+	if (IS_ERR(dc->fbdev)) {
+		dev_err(dev->dev, "failed to setup fbdev\n");
+		ret = PTR_ERR(dc->fbdev);
+		goto err_cleanup_poll;
+	}
 
 	return 0;
 
+err_cleanup_poll:
+	drm_kms_helper_poll_fini(dev);
+
+	pm_runtime_get_sync(dev->dev);
+	drm_irq_uninstall(dev);
+	pm_runtime_put_sync(dev->dev);
+
 err_periph_clk_disable:
 	pm_runtime_disable(dev->dev);
 	clk_disable_unprepare(dc->hlcdc->periph_clk);
-- 
2.8.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/4] drm/exynos: Remove custom FB helper deferred setup
  2016-06-03 16:11 [PATCH 1/4] drm/fb-helper: Support deferred setup Thierry Reding
  2016-06-03 16:11 ` [PATCH 2/4] drm/atmel-hlcdc: Remove custom FB helper " Thierry Reding
@ 2016-06-03 16:11 ` Thierry Reding
  2016-06-03 16:11 ` [PATCH 4/4] drm/hisilicon: " Thierry Reding
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Thierry Reding @ 2016-06-03 16:11 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Xinliang Liu, Chen Feng, Seung-Woo Kim, dri-devel, Kyungmin Park

From: Thierry Reding <treding@nvidia.com>

The FB helper core now supports deferred setup, so the driver's custom
implementation can be removed.

Cc: Inki Dae <inki.dae@samsung.com>
Cc: Joonyoung Shim <jy0922.shim@samsung.com>
Cc: Seung-Woo Kim <sw0312.kim@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Compile-tested only.

 drivers/gpu/drm/exynos/exynos_drm_drv.c   | 8 ++++++--
 drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 2 --
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 2dd820e23b0c..259c2585c703 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -215,11 +215,15 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 	/* init kms poll for handling hpd */
 	drm_kms_helper_poll_init(dev);
 
-	/* force connectors detection */
-	drm_helper_hpd_irq_event(dev);
+	ret = exynos_drm_fbdev_init(dev);
+	if (ret)
+		goto err_cleanup_poll;
 
 	return 0;
 
+err_cleanup_poll:
+	drm_kms_helper_poll_fini(dev);
+	exynos_drm_device_subdrv_remove(dev);
 err_cleanup_vblank:
 	drm_vblank_cleanup(dev);
 err_unbind_all:
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index 67dcd6831291..83a277946200 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -319,6 +319,4 @@ void exynos_drm_output_poll_changed(struct drm_device *dev)
 
 	if (fb_helper)
 		drm_fb_helper_hotplug_event(fb_helper);
-	else
-		exynos_drm_fbdev_init(dev);
 }
-- 
2.8.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/4] drm/hisilicon: Remove custom FB helper deferred setup
  2016-06-03 16:11 [PATCH 1/4] drm/fb-helper: Support deferred setup Thierry Reding
  2016-06-03 16:11 ` [PATCH 2/4] drm/atmel-hlcdc: Remove custom FB helper " Thierry Reding
  2016-06-03 16:11 ` [PATCH 3/4] drm/exynos: " Thierry Reding
@ 2016-06-03 16:11 ` Thierry Reding
  2016-06-03 18:40   ` Daniel Vetter
  2016-06-03 18:33 ` [PATCH 1/4] drm/fb-helper: Support " Daniel Vetter
  2016-06-04 10:46 ` Lukas Wunner
  4 siblings, 1 reply; 7+ messages in thread
From: Thierry Reding @ 2016-06-03 16:11 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Xinliang Liu, Chen Feng, Seung-Woo Kim, dri-devel, Kyungmin Park

From: Thierry Reding <treding@nvidia.com>

The FB helper core now supports deferred setup, so the driver's custom
implementation can be removed.

Cc: Xinliang Liu <z.liuxinliang@hisilicon.com>
Cc: Xinwei Kong <kong.kongxinwei@hisilicon.com>
Cc: Chen Feng <puck.chen@hisilicon.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Compile-tested only.

 drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
index 3f94785fbcca..0e0bd77e4499 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
@@ -54,15 +54,7 @@ static void kirin_fbdev_output_poll_changed(struct drm_device *dev)
 {
 	struct kirin_drm_private *priv = dev->dev_private;
 
-	if (priv->fbdev) {
-		drm_fbdev_cma_hotplug_event(priv->fbdev);
-	} else {
-		priv->fbdev = drm_fbdev_cma_init(dev, 32,
-				dev->mode_config.num_crtc,
-				dev->mode_config.num_connector);
-		if (IS_ERR(priv->fbdev))
-			priv->fbdev = NULL;
-	}
+	drm_fbdev_cma_hotplug_event(priv->fbdev);
 }
 #endif
 
@@ -129,11 +121,19 @@ static int kirin_drm_kms_init(struct drm_device *dev)
 	/* init kms poll for handling hpd */
 	drm_kms_helper_poll_init(dev);
 
-	/* force detection after connectors init */
-	(void)drm_helper_hpd_irq_event(dev);
+	priv->fbdev = drm_fbdev_cma_init(dev, 32, dev->mode_config.num_crtc,
+					 dev->mode_config.num_connector);
+	if (IS_ERR(priv->fbdev)) {
+		DRM_ERROR("failed to initialize fbdev.\n");
+		ret = PTR_ERR(priv->fbdev);
+		goto err_cleanup_poll;
+	}
 
 	return 0;
 
+err_cleanup_poll:
+	drm_kms_helper_poll_fini(dev);
+	drm_vblank_cleanup(dev);
 err_unbind_all:
 	component_unbind_all(dev->dev, dev);
 err_dc_cleanup:
-- 
2.8.3

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/4] drm/fb-helper: Support deferred setup
  2016-06-03 16:11 [PATCH 1/4] drm/fb-helper: Support deferred setup Thierry Reding
                   ` (2 preceding siblings ...)
  2016-06-03 16:11 ` [PATCH 4/4] drm/hisilicon: " Thierry Reding
@ 2016-06-03 18:33 ` Daniel Vetter
  2016-06-04 10:46 ` Lukas Wunner
  4 siblings, 0 replies; 7+ messages in thread
From: Daniel Vetter @ 2016-06-03 18:33 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Xinliang Liu, Daniel Vetter, Seung-Woo Kim, dri-devel,
	Kyungmin Park, Chen Feng

On Fri, Jun 03, 2016 at 06:11:16PM +0200, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> FB helper code falls back to a 1024x768 mode if no outputs are connected
> or don't report back any modes upon initialization. This can be annoying
> because outputs that are added to FB helper later on can't be used with
> FB helper if they don't support a matching mode.
> 
> The fallback is in place because VGA connectors can happen to report an
> unknown connection status even when they are in fact connected.
> 
> Some drivers have custom solutions in place to defer FB helper setup
> until at least one output is connected. But the logic behind these
> solutions is always the same and there is nothing driver-specific about
> it, so a better alterative is to fix the FB helper core and add support
> for all drivers automatically.
> 
> This patch adds support for deferred FB helper setup. It checks all the
> connectors for their connection status, and if all of them report to be
> disconnected marks the FB helper as needing deferred setup. Whet setup
> is deferred, the FB helper core will automatically retry setup after a
> hotplug event, and it will keep trying until it succeeds.
> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  drivers/gpu/drm/drm_fb_helper.c | 36 ++++++++++++++++++++++++++++++++++++
>  include/drm/drm_fb_helper.h     | 21 +++++++++++++++++++++
>  2 files changed, 57 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index 7c2eb75db60f..4f334f9cab28 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -442,6 +442,9 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
>  	if (!drm_fbdev_emulation)
>  		return -ENODEV;
>  
> +	if (fb_helper->deferred_setup)
> +		return 0;
> +
>  	drm_modeset_lock_all(dev);
>  	ret = restore_fbdev_mode(fb_helper);
>  
> @@ -1398,6 +1401,23 @@ unlock:
>  }
>  EXPORT_SYMBOL(drm_fb_helper_pan_display);
>  
> +static bool drm_fb_helper_maybe_connected(struct drm_fb_helper *helper)
> +{
> +	bool connected = false;
> +	unsigned int i;
> +
> +	for (i = 0; i < helper->connector_count; i++) {
> +		struct drm_fb_helper_connector *fb = helper->connector_info[i];
> +
> +		if (fb->connector->status != connector_status_disconnected) {
> +			connected = true;
> +			break;
> +		}
> +	}
> +
> +	return connected;
> +}
> +
>  /*
>   * Allocates the backing storage and sets up the fbdev info structure through
>   * the ->fb_probe callback and then registers the fbdev and sets up the panic
> @@ -1499,6 +1519,17 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
>  			sizes.fb_height = min_t(u32, desired_mode->vdisplay + y, sizes.fb_height);
>  	}
>  
> +	/*
> +	 * If everything's disconnected, there's no use in attempting to set
> +	 * up fbdev.
> +	 */
> +	if (!drm_fb_helper_maybe_connected(fb_helper)) {
> +		DRM_INFO("No outputs connected, deferring setup\n");
> +		fb_helper->preferred_bpp = preferred_bpp;
> +		fb_helper->deferred_setup = true;
> +		return 0;
> +	}
> +
>  	if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
>  		/* hmm everyone went away - assume VGA cable just fell out
>  		   and will come back later. */
> @@ -1539,6 +1570,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
>  
>  	list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
>  
> +	fb_helper->deferred_setup = false;
>  	return 0;
>  }
>  
> @@ -2237,6 +2269,10 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
>  	if (!drm_fbdev_emulation)
>  		return 0;
>  
> +	if (fb_helper->deferred_setup)
> +		return drm_fb_helper_initial_config(fb_helper,
> +						    fb_helper->preferred_bpp);

Logic looks all nice, but we need more locking. Extending our abuse of
dev->mode_config.mutex for fb_helper internals won't work since
initial_config already takes some locks at various times, we need a real
fb_helper->mutex now. We want that anyway, to be able to push a bunch of
the modeset locking out of the fbdev code, or at least down a lot.

To make it work we need to make it a top-level lock, surrounding all kms
locks I think. And minimally it needs to wrapt hotplug_event, restore_mode
and the single_add/remove_connector functions.
-Daniel

> +
>  	mutex_lock(&fb_helper->dev->mode_config.mutex);
>  	if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) {
>  		fb_helper->delayed_hotplug = true;
> diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
> index 5b4aa35026a3..25446690b2c1 100644
> --- a/include/drm/drm_fb_helper.h
> +++ b/include/drm/drm_fb_helper.h
> @@ -214,6 +214,27 @@ struct drm_fb_helper {
>  	bool delayed_hotplug;
>  
>  	/**
> +	 * @deferred_setup:
> +	 *
> +	 * If no outputs are connected (disconnected or unknown) the FB helper
> +	 * code will defer setup until at least one of the outputs shows up.
> +	 * This field keeps track of the status so that setup can be retried
> +	 * at every hotplug event until it succeeds eventually.
> +	 */
> +	bool deferred_setup;
> +
> +	/**
> +	 * @preferred_bpp:
> +	 *
> +	 * Temporary storage for the driver's preferred BPP setting passed to
> +	 * FB helper initialization. This needs to be tracked so that deferred
> +	 * FB helper setup can pass this on.
> +	 *
> +	 * See also: @deferred_setup
> +	 */
> +	int preferred_bpp;
> +
> +	/**
>  	 * @atomic:
>  	 *
>  	 * Use atomic updates for restore_fbdev_mode(), etc.  This defaults to
> -- 
> 2.8.3
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 4/4] drm/hisilicon: Remove custom FB helper deferred setup
  2016-06-03 16:11 ` [PATCH 4/4] drm/hisilicon: " Thierry Reding
@ 2016-06-03 18:40   ` Daniel Vetter
  0 siblings, 0 replies; 7+ messages in thread
From: Daniel Vetter @ 2016-06-03 18:40 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Xinliang Liu, Daniel Vetter, Seung-Woo Kim, dri-devel,
	Kyungmin Park, Chen Feng

On Fri, Jun 03, 2016 at 06:11:19PM +0200, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> The FB helper core now supports deferred setup, so the driver's custom
> implementation can be removed.
> 
> Cc: Xinliang Liu <z.liuxinliang@hisilicon.com>
> Cc: Xinwei Kong <kong.kongxinwei@hisilicon.com>
> Cc: Chen Feng <puck.chen@hisilicon.com>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
> Compile-tested only.
> 
>  drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 22 +++++++++++-----------
>  1 file changed, 11 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> index 3f94785fbcca..0e0bd77e4499 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> @@ -54,15 +54,7 @@ static void kirin_fbdev_output_poll_changed(struct drm_device *dev)
>  {
>  	struct kirin_drm_private *priv = dev->dev_private;
>  
> -	if (priv->fbdev) {
> -		drm_fbdev_cma_hotplug_event(priv->fbdev);
> -	} else {
> -		priv->fbdev = drm_fbdev_cma_init(dev, 32,
> -				dev->mode_config.num_crtc,
> -				dev->mode_config.num_connector);
> -		if (IS_ERR(priv->fbdev))
> -			priv->fbdev = NULL;
> -	}
> +	drm_fbdev_cma_hotplug_event(priv->fbdev);

btw spotted a pile more if (priv->fbdev) conditions which could all be
removed for drm_fbdev_cma_hotplug_event, since that has that check
already. Care to type those patches and throw it on top?

Otherwise didn't spot anything in the driver conversion, lgtm for patches
2-4.
-Daniel

>  }
>  #endif
>  
> @@ -129,11 +121,19 @@ static int kirin_drm_kms_init(struct drm_device *dev)
>  	/* init kms poll for handling hpd */
>  	drm_kms_helper_poll_init(dev);
>  
> -	/* force detection after connectors init */
> -	(void)drm_helper_hpd_irq_event(dev);
> +	priv->fbdev = drm_fbdev_cma_init(dev, 32, dev->mode_config.num_crtc,
> +					 dev->mode_config.num_connector);
> +	if (IS_ERR(priv->fbdev)) {
> +		DRM_ERROR("failed to initialize fbdev.\n");
> +		ret = PTR_ERR(priv->fbdev);
> +		goto err_cleanup_poll;
> +	}
>  
>  	return 0;
>  
> +err_cleanup_poll:
> +	drm_kms_helper_poll_fini(dev);
> +	drm_vblank_cleanup(dev);
>  err_unbind_all:
>  	component_unbind_all(dev->dev, dev);
>  err_dc_cleanup:
> -- 
> 2.8.3
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/4] drm/fb-helper: Support deferred setup
  2016-06-03 16:11 [PATCH 1/4] drm/fb-helper: Support deferred setup Thierry Reding
                   ` (3 preceding siblings ...)
  2016-06-03 18:33 ` [PATCH 1/4] drm/fb-helper: Support " Daniel Vetter
@ 2016-06-04 10:46 ` Lukas Wunner
  4 siblings, 0 replies; 7+ messages in thread
From: Lukas Wunner @ 2016-06-04 10:46 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Daniel Vetter, Seung-Woo Kim, dri-devel, Xinliang Liu,
	Kyungmin Park, Chen Feng

On Fri, Jun 03, 2016 at 06:11:16PM +0200, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> FB helper code falls back to a 1024x768 mode if no outputs are connected
> or don't report back any modes upon initialization. This can be annoying
> because outputs that are added to FB helper later on can't be used with
> FB helper if they don't support a matching mode.
> 
> The fallback is in place because VGA connectors can happen to report an
> unknown connection status even when they are in fact connected.
> 
> Some drivers have custom solutions in place to defer FB helper setup
> until at least one output is connected. But the logic behind these
> solutions is always the same and there is nothing driver-specific about
> it, so a better alterative is to fix the FB helper core and add support
> for all drivers automatically.
> 
> This patch adds support for deferred FB helper setup. It checks all the
> connectors for their connection status, and if all of them report to be
> disconnected marks the FB helper as needing deferred setup. Whet setup
> is deferred, the FB helper core will automatically retry setup after a
> hotplug event, and it will keep trying until it succeeds.

This might have been an alternative solution to the driver dependencies
I was experiencing with GPU switching on the MacBook Pro: The apple-gmux
module needs to be loaded on pre-retinas to switch DDC, and on retinas
the DRM driver for the active GPU needs to have set up the eDP output
so that the inactive GPU can use the pre-calibrated v-swing, pre-emph etc.

I tried something similar to this patch here first, falling back to
1024x786 if the dependencies weren't met, and then tearing down and
reinitializing the fbdev once all prerequisites were fulfilled.
This approach turned out to be too fragile so I settled on -EPROBE_DEFER,
which had the additional advantage of needing much less code.

I'm not sure if a hotplug signal is generated at all on older machines
with a plain vanilla VGA output. If that is not the case, this patch
here will cause a change of behaviour.

It also doesn't solve the issue that a display is unplugged and replaced
with a larger display. The fb resolution will stay the same. Ideally we
should tear down the fbdev if the last display using it is unplugged and
recreate it once something is plugged in again.

Best regards,

Lukas

> 
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  drivers/gpu/drm/drm_fb_helper.c | 36 ++++++++++++++++++++++++++++++++++++
>  include/drm/drm_fb_helper.h     | 21 +++++++++++++++++++++
>  2 files changed, 57 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index 7c2eb75db60f..4f334f9cab28 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -442,6 +442,9 @@ int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
>  	if (!drm_fbdev_emulation)
>  		return -ENODEV;
>  
> +	if (fb_helper->deferred_setup)
> +		return 0;
> +
>  	drm_modeset_lock_all(dev);
>  	ret = restore_fbdev_mode(fb_helper);
>  
> @@ -1398,6 +1401,23 @@ unlock:
>  }
>  EXPORT_SYMBOL(drm_fb_helper_pan_display);
>  
> +static bool drm_fb_helper_maybe_connected(struct drm_fb_helper *helper)
> +{
> +	bool connected = false;
> +	unsigned int i;
> +
> +	for (i = 0; i < helper->connector_count; i++) {
> +		struct drm_fb_helper_connector *fb = helper->connector_info[i];
> +
> +		if (fb->connector->status != connector_status_disconnected) {
> +			connected = true;
> +			break;
> +		}
> +	}
> +
> +	return connected;
> +}
> +
>  /*
>   * Allocates the backing storage and sets up the fbdev info structure through
>   * the ->fb_probe callback and then registers the fbdev and sets up the panic
> @@ -1499,6 +1519,17 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
>  			sizes.fb_height = min_t(u32, desired_mode->vdisplay + y, sizes.fb_height);
>  	}
>  
> +	/*
> +	 * If everything's disconnected, there's no use in attempting to set
> +	 * up fbdev.
> +	 */
> +	if (!drm_fb_helper_maybe_connected(fb_helper)) {
> +		DRM_INFO("No outputs connected, deferring setup\n");
> +		fb_helper->preferred_bpp = preferred_bpp;
> +		fb_helper->deferred_setup = true;
> +		return 0;
> +	}
> +
>  	if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
>  		/* hmm everyone went away - assume VGA cable just fell out
>  		   and will come back later. */
> @@ -1539,6 +1570,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
>  
>  	list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
>  
> +	fb_helper->deferred_setup = false;
>  	return 0;
>  }
>  
> @@ -2237,6 +2269,10 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
>  	if (!drm_fbdev_emulation)
>  		return 0;
>  
> +	if (fb_helper->deferred_setup)
> +		return drm_fb_helper_initial_config(fb_helper,
> +						    fb_helper->preferred_bpp);
> +
>  	mutex_lock(&fb_helper->dev->mode_config.mutex);
>  	if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) {
>  		fb_helper->delayed_hotplug = true;
> diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
> index 5b4aa35026a3..25446690b2c1 100644
> --- a/include/drm/drm_fb_helper.h
> +++ b/include/drm/drm_fb_helper.h
> @@ -214,6 +214,27 @@ struct drm_fb_helper {
>  	bool delayed_hotplug;
>  
>  	/**
> +	 * @deferred_setup:
> +	 *
> +	 * If no outputs are connected (disconnected or unknown) the FB helper
> +	 * code will defer setup until at least one of the outputs shows up.
> +	 * This field keeps track of the status so that setup can be retried
> +	 * at every hotplug event until it succeeds eventually.
> +	 */
> +	bool deferred_setup;
> +
> +	/**
> +	 * @preferred_bpp:
> +	 *
> +	 * Temporary storage for the driver's preferred BPP setting passed to
> +	 * FB helper initialization. This needs to be tracked so that deferred
> +	 * FB helper setup can pass this on.
> +	 *
> +	 * See also: @deferred_setup
> +	 */
> +	int preferred_bpp;
> +
> +	/**
>  	 * @atomic:
>  	 *
>  	 * Use atomic updates for restore_fbdev_mode(), etc.  This defaults to
> -- 
> 2.8.3
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-06-04 10:42 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-06-03 16:11 [PATCH 1/4] drm/fb-helper: Support deferred setup Thierry Reding
2016-06-03 16:11 ` [PATCH 2/4] drm/atmel-hlcdc: Remove custom FB helper " Thierry Reding
2016-06-03 16:11 ` [PATCH 3/4] drm/exynos: " Thierry Reding
2016-06-03 16:11 ` [PATCH 4/4] drm/hisilicon: " Thierry Reding
2016-06-03 18:40   ` Daniel Vetter
2016-06-03 18:33 ` [PATCH 1/4] drm/fb-helper: Support " Daniel Vetter
2016-06-04 10:46 ` Lukas Wunner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox