drm/i915: Return -EPROBE_DEFER if we cannot get GPIO or PWM in dsi_init
diff mbox

Message ID 1468573390-26617-1-git-send-email-shobhit.kumar@intel.com
State New
Headers show

Commit Message

Kumar, Shobhit July 15, 2016, 9:03 a.m. UTC
On devices that have MIPI DSI panel control and PWM control comming from
CRC PMIC, we need the gpio and pwm exported from the intel_soc_pmic
driver. Defer probing for later in case we fail to get these devices.

v2: Rebased on latest drm-intel-nightly
    Added failure check for pwm_get which got missed out

Signed-off-by: Shobhit Kumar <shobhit.kumar@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c      |  4 ++++
 drivers/gpu/drm/i915/i915_drv.h      |  2 +-
 drivers/gpu/drm/i915/intel_display.c | 25 +++++++++++++++++++------
 drivers/gpu/drm/i915/intel_drv.h     |  2 +-
 drivers/gpu/drm/i915/intel_dsi.c     | 24 +++++++++++++++++-------
 5 files changed, 42 insertions(+), 15 deletions(-)

Comments

Shobhit Kumar July 15, 2016, 9:08 a.m. UTC | #1
On Fri, Jul 15, 2016 at 2:33 PM, Shobhit Kumar <shobhit.kumar@intel.com> wrote:
> On devices that have MIPI DSI panel control and PWM control comming from
> CRC PMIC, we need the gpio and pwm exported from the intel_soc_pmic
> driver. Defer probing for later in case we fail to get these devices.
>
> v2: Rebased on latest drm-intel-nightly
>     Added failure check for pwm_get which got missed out
>

Just an attempt and is untested yet because of lack of device which
use CRC PMIC or LPSS. Hopefully can get some testing help from Stephen
and  Viric who have such devices.

Regards
Shobhit

> Signed-off-by: Shobhit Kumar <shobhit.kumar@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c      |  4 ++++
>  drivers/gpu/drm/i915/i915_drv.h      |  2 +-
>  drivers/gpu/drm/i915/intel_display.c | 25 +++++++++++++++++++------
>  drivers/gpu/drm/i915/intel_drv.h     |  2 +-
>  drivers/gpu/drm/i915/intel_dsi.c     | 24 +++++++++++++++++-------
>  5 files changed, 42 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index b9a8117..9bfe0c8 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -648,6 +648,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
>         /* Important: The output setup functions called by modeset_init need
>          * working irqs for e.g. gmbus and dp aux transfers. */
>         intel_modeset_init(dev);
> +       ret = intel_modeset_init(dev);
> +       if (ret == -EPROBE_DEFER)
> +               goto cleanup_deffered_probe;
>
>         intel_guc_init(dev);
>
> @@ -675,6 +678,7 @@ cleanup_gem:
>         i915_gem_fini(dev);
>  cleanup_irq:
>         intel_guc_fini(dev);
> +cleanup_deffered_probe:
>         drm_irq_uninstall(dev);
>         intel_teardown_gmbus(dev);
>  cleanup_csr:
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 03e1bfa..a9eed22 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -3778,7 +3778,7 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv);
>
>  /* modesetting */
>  extern void intel_modeset_init_hw(struct drm_device *dev);
> -extern void intel_modeset_init(struct drm_device *dev);
> +extern int intel_modeset_init(struct drm_device *dev);
>  extern void intel_modeset_gem_init(struct drm_device *dev);
>  extern void intel_modeset_cleanup(struct drm_device *dev);
>  extern int intel_connector_register(struct drm_connector *);
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index be3b2ca..b1250f2 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -14612,11 +14612,12 @@ static bool intel_crt_present(struct drm_device *dev)
>         return true;
>  }
>
> -static void intel_setup_outputs(struct drm_device *dev)
> +static int intel_setup_outputs(struct drm_device *dev)
>  {
>         struct drm_i915_private *dev_priv = to_i915(dev);
>         struct intel_encoder *encoder;
>         bool dpd_is_edp = false;
> +       int ret = 0;
>
>         /*
>          * intel_edp_init_connector() depends on this completing first, to
> @@ -14638,7 +14639,9 @@ static void intel_setup_outputs(struct drm_device *dev)
>                 intel_ddi_init(dev, PORT_B);
>                 intel_ddi_init(dev, PORT_C);
>
> -               intel_dsi_init(dev);
> +               ret = intel_dsi_init(dev);
> +               if (ret == -EPROBE_DEFER)
> +                       return ret;
>         } else if (HAS_DDI(dev)) {
>                 int found;
>
> @@ -14742,7 +14745,9 @@ static void intel_setup_outputs(struct drm_device *dev)
>                                 intel_hdmi_init(dev, CHV_HDMID, PORT_D);
>                 }
>
> -               intel_dsi_init(dev);
> +               ret = intel_dsi_init(dev);
> +               if (ret == -EPROBE_DEFER)
> +                       return ret;
>         } else if (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) {
>                 bool found = false;
>
> @@ -14795,6 +14800,8 @@ static void intel_setup_outputs(struct drm_device *dev)
>         intel_init_pch_refclk(dev);
>
>         drm_helper_move_panel_connectors_to_head(dev);
> +
> +       return 0;
>  }
>
>  static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
> @@ -15539,7 +15546,7 @@ fail:
>         drm_modeset_acquire_fini(&ctx);
>  }
>
> -void intel_modeset_init(struct drm_device *dev)
> +int intel_modeset_init(struct drm_device *dev)
>  {
>         struct drm_i915_private *dev_priv = to_i915(dev);
>         struct i915_ggtt *ggtt = &dev_priv->ggtt;
> @@ -15564,7 +15571,7 @@ void intel_modeset_init(struct drm_device *dev)
>         intel_init_pm(dev);
>
>         if (INTEL_INFO(dev)->num_pipes == 0)
> -               return;
> +               return 0;
>
>         /*
>          * There may be no VBT; and if the BIOS enabled SSC we can
> @@ -15632,7 +15639,11 @@ void intel_modeset_init(struct drm_device *dev)
>
>         /* Just disable it once at startup */
>         i915_disable_vga(dev);
> -       intel_setup_outputs(dev);
> +
> +       /* Check if we encountered -EPROBE_DEFER while initializing DSI */
> +       ret = intel_setup_outputs(dev);
> +       if (ret)
> +               return ret;
>
>         drm_modeset_lock_all(dev);
>         intel_modeset_setup_hw_state(dev);
> @@ -15667,6 +15678,8 @@ void intel_modeset_init(struct drm_device *dev)
>          * since the watermark calculation done here will use pstate->fb.
>          */
>         sanitize_watermarks(dev);
> +
> +       return 0;
>  }
>
>  static void intel_enable_pipe_a(struct drm_device *dev)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 55aeaf0..4f05b7c 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1418,7 +1418,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector);
>  int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
>  void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
>  /* intel_dsi.c */
> -void intel_dsi_init(struct drm_device *dev);
> +int intel_dsi_init(struct drm_device *dev);
>
>  /* intel_dsi_dcs_backlight.c */
>  int intel_dsi_dcs_init_backlight_funcs(struct intel_connector *intel_connector);
> diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
> index de8e9fb..5c02a3f 100644
> --- a/drivers/gpu/drm/i915/intel_dsi.c
> +++ b/drivers/gpu/drm/i915/intel_dsi.c
> @@ -1422,7 +1422,7 @@ static void intel_dsi_add_properties(struct intel_connector *connector)
>         }
>  }
>
> -void intel_dsi_init(struct drm_device *dev)
> +int intel_dsi_init(struct drm_device *dev)
>  {
>         struct intel_dsi *intel_dsi;
>         struct intel_encoder *intel_encoder;
> @@ -1433,12 +1433,13 @@ void intel_dsi_init(struct drm_device *dev)
>         struct drm_i915_private *dev_priv = to_i915(dev);
>         enum port port;
>         unsigned int i;
> +       int ret = 0;
>
>         DRM_DEBUG_KMS("\n");
>
>         /* There is no detection method for MIPI so rely on VBT */
>         if (!intel_bios_is_dsi_present(dev_priv, &port))
> -               return;
> +               return 0;
>
>         if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
>                 dev_priv->mipi_mmio_base = VLV_MIPI_BASE;
> @@ -1446,17 +1447,17 @@ void intel_dsi_init(struct drm_device *dev)
>                 dev_priv->mipi_mmio_base = BXT_MIPI_BASE;
>         } else {
>                 DRM_ERROR("Unsupported Mipi device to reg base");
> -               return;
> +               return 0;
>         }
>
>         intel_dsi = kzalloc(sizeof(*intel_dsi), GFP_KERNEL);
>         if (!intel_dsi)
> -               return;
> +               return -ENOMEM;
>
>         intel_connector = intel_connector_alloc();
>         if (!intel_connector) {
>                 kfree(intel_dsi);
> -               return;
> +               return -ENOMEM;
>         }
>
>         intel_encoder = &intel_dsi->base;
> @@ -1560,6 +1561,9 @@ void intel_dsi_init(struct drm_device *dev)
>                 if (IS_ERR(intel_dsi->gpio_panel)) {
>                         DRM_ERROR("Failed to own gpio for panel control\n");
>                         intel_dsi->gpio_panel = NULL;
> +
> +                       ret = -EPROBE_DEFER;
> +                       goto err;
>                 }
>         }
>
> @@ -1597,14 +1601,20 @@ void intel_dsi_init(struct drm_device *dev)
>         connector->display_info.height_mm = fixed_mode->height_mm;
>
>         intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
> -       intel_panel_setup_backlight(connector, INVALID_PIPE);
> +       ret = intel_panel_setup_backlight(connector, INVALID_PIPE);
> +       if (ret == -ENODEV) {
> +               ret = -EPROBE_DEFER;
> +               goto err;
> +       }
>
>         intel_dsi_add_properties(intel_connector);
>
> -       return;
> +       return 0;
>
>  err:
>         drm_encoder_cleanup(&intel_encoder->base);
>         kfree(intel_dsi);
>         kfree(intel_connector);
> +
> +       return ret;
>  }
> --
> 2.5.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Stephen Just July 15, 2016, 9:42 p.m. UTC | #2
On Fri, Jul 15, 2016 at 3:08 AM, Shobhit Kumar <kumar@shobhit.info> wrote:
>
> On Fri, Jul 15, 2016 at 2:33 PM, Shobhit Kumar <shobhit.kumar@intel.com> wrote:
> > On devices that have MIPI DSI panel control and PWM control comming from
> > CRC PMIC, we need the gpio and pwm exported from the intel_soc_pmic
> > driver. Defer probing for later in case we fail to get these devices.
> >
> > v2: Rebased on latest drm-intel-nightly
> >     Added failure check for pwm_get which got missed out
> >
>
> [snip]
>
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > index b9a8117..9bfe0c8 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -648,6 +648,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
> >         /* Important: The output setup functions called by modeset_init need
> >          * working irqs for e.g. gmbus and dp aux transfers. */
> >         intel_modeset_init(dev);
> > +       ret = intel_modeset_init(dev);
> > +       if (ret == -EPROBE_DEFER)
> > +               goto cleanup_deffered_probe;

Did you intend to call intel_modeset_init twice? In my tests, I
removed the first copy because it seemed like a mistake.

> >
> >         intel_guc_init(dev);
> >
> > @@ -675,6 +678,7 @@ cleanup_gem:
> >         i915_gem_fini(dev);
> >  cleanup_irq:
> >         intel_guc_fini(dev);
> > +cleanup_deffered_probe:
> >         drm_irq_uninstall(dev);
> >         intel_teardown_gmbus(dev);
> >  cleanup_csr:
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 03e1bfa..a9eed22 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -3778,7 +3778,7 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv);
> >
> >  /* modesetting */
> >  extern void intel_modeset_init_hw(struct drm_device *dev);
> > -extern void intel_modeset_init(struct drm_device *dev);
> > +extern int intel_modeset_init(struct drm_device *dev);
> >  extern void intel_modeset_gem_init(struct drm_device *dev);
> >  extern void intel_modeset_cleanup(struct drm_device *dev);
> >  extern int intel_connector_register(struct drm_connector *);
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index be3b2ca..b1250f2 100644
> > [snip]

When testing on drm-intel-nightly, my system froze with your patch. I
can't get a full dmesg because I haven't yet found a way to trigger
the problem after I can get an ssh session up.

The relevant logs I see before freeze are:
[drm] Initialized drm 1.1.0 20060810
[drm] Memory usable by graphics device = 2048M
fb: switching to inteldrmfb from EFI VGA

console is stuck at this point, my guess is that modeset fails and
that isn't handled well. The screen does not go black, the log
messages just stay on screen indefinitely.

If I blacklist i915 and let X load the module (or manually load it
later), everything seems to run fine and backlight works, but that was
also true before applying the patch.

Regards,
Stephen
Shobhit Kumar July 16, 2016, 10:39 a.m. UTC | #3
On Sat, Jul 16, 2016 at 3:12 AM, Stephen J <stephenjust@gmail.com> wrote:
> On Fri, Jul 15, 2016 at 3:08 AM, Shobhit Kumar <kumar@shobhit.info> wrote:
>>
>> On Fri, Jul 15, 2016 at 2:33 PM, Shobhit Kumar <shobhit.kumar@intel.com> wrote:
>> > On devices that have MIPI DSI panel control and PWM control comming from
>> > CRC PMIC, we need the gpio and pwm exported from the intel_soc_pmic
>> > driver. Defer probing for later in case we fail to get these devices.
>> >
>> > v2: Rebased on latest drm-intel-nightly
>> >     Added failure check for pwm_get which got missed out
>> >
>>
>> [snip]
>>
>> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
>> > index b9a8117..9bfe0c8 100644
>> > --- a/drivers/gpu/drm/i915/i915_drv.c
>> > +++ b/drivers/gpu/drm/i915/i915_drv.c
>> > @@ -648,6 +648,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
>> >         /* Important: The output setup functions called by modeset_init need
>> >          * working irqs for e.g. gmbus and dp aux transfers. */
>> >         intel_modeset_init(dev);
>> > +       ret = intel_modeset_init(dev);
>> > +       if (ret == -EPROBE_DEFER)
>> > +               goto cleanup_deffered_probe;
>
> Did you intend to call intel_modeset_init twice? In my tests, I
> removed the first copy because it seemed like a mistake.
>

Nope I did not. It was a mistake. Thanks for pointing out.

>> >
>> >         intel_guc_init(dev);
>> >
>> > @@ -675,6 +678,7 @@ cleanup_gem:
>> >         i915_gem_fini(dev);
>> >  cleanup_irq:
>> >         intel_guc_fini(dev);
>> > +cleanup_deffered_probe:
>> >         drm_irq_uninstall(dev);
>> >         intel_teardown_gmbus(dev);
>> >  cleanup_csr:
>> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> > index 03e1bfa..a9eed22 100644
>> > --- a/drivers/gpu/drm/i915/i915_drv.h
>> > +++ b/drivers/gpu/drm/i915/i915_drv.h
>> > @@ -3778,7 +3778,7 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv);
>> >
>> >  /* modesetting */
>> >  extern void intel_modeset_init_hw(struct drm_device *dev);
>> > -extern void intel_modeset_init(struct drm_device *dev);
>> > +extern int intel_modeset_init(struct drm_device *dev);
>> >  extern void intel_modeset_gem_init(struct drm_device *dev);
>> >  extern void intel_modeset_cleanup(struct drm_device *dev);
>> >  extern int intel_connector_register(struct drm_connector *);
>> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> > index be3b2ca..b1250f2 100644
>> > [snip]
>
> When testing on drm-intel-nightly, my system froze with your patch. I
> can't get a full dmesg because I haven't yet found a way to trigger
> the problem after I can get an ssh session up.
>
> The relevant logs I see before freeze are:
> [drm] Initialized drm 1.1.0 20060810
> [drm] Memory usable by graphics device = 2048M
> fb: switching to inteldrmfb from EFI VGA
>
> console is stuck at this point, my guess is that modeset fails and
> that isn't handled well. The screen does not go black, the log
> messages just stay on screen indefinitely.

Will try to force deferred probe on one of my device which has serial
console to get the serial logs and debug deferred probe in general.

Regards
Shobhit

>
> If I blacklist i915 and let X load the module (or manually load it
> later), everything seems to run fine and backlight works, but that was
> also true before applying the patch.
>
> Regards,
> Stephen

Patch
diff mbox

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index b9a8117..9bfe0c8 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -648,6 +648,9 @@  static int i915_load_modeset_init(struct drm_device *dev)
 	/* Important: The output setup functions called by modeset_init need
 	 * working irqs for e.g. gmbus and dp aux transfers. */
 	intel_modeset_init(dev);
+	ret = intel_modeset_init(dev);
+	if (ret == -EPROBE_DEFER)
+		goto cleanup_deffered_probe;
 
 	intel_guc_init(dev);
 
@@ -675,6 +678,7 @@  cleanup_gem:
 	i915_gem_fini(dev);
 cleanup_irq:
 	intel_guc_fini(dev);
+cleanup_deffered_probe:
 	drm_irq_uninstall(dev);
 	intel_teardown_gmbus(dev);
 cleanup_csr:
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 03e1bfa..a9eed22 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3778,7 +3778,7 @@  void intel_device_info_dump(struct drm_i915_private *dev_priv);
 
 /* modesetting */
 extern void intel_modeset_init_hw(struct drm_device *dev);
-extern void intel_modeset_init(struct drm_device *dev);
+extern int intel_modeset_init(struct drm_device *dev);
 extern void intel_modeset_gem_init(struct drm_device *dev);
 extern void intel_modeset_cleanup(struct drm_device *dev);
 extern int intel_connector_register(struct drm_connector *);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index be3b2ca..b1250f2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -14612,11 +14612,12 @@  static bool intel_crt_present(struct drm_device *dev)
 	return true;
 }
 
-static void intel_setup_outputs(struct drm_device *dev)
+static int intel_setup_outputs(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_encoder *encoder;
 	bool dpd_is_edp = false;
+	int ret = 0;
 
 	/*
 	 * intel_edp_init_connector() depends on this completing first, to
@@ -14638,7 +14639,9 @@  static void intel_setup_outputs(struct drm_device *dev)
 		intel_ddi_init(dev, PORT_B);
 		intel_ddi_init(dev, PORT_C);
 
-		intel_dsi_init(dev);
+		ret = intel_dsi_init(dev);
+		if (ret == -EPROBE_DEFER)
+			return ret;
 	} else if (HAS_DDI(dev)) {
 		int found;
 
@@ -14742,7 +14745,9 @@  static void intel_setup_outputs(struct drm_device *dev)
 				intel_hdmi_init(dev, CHV_HDMID, PORT_D);
 		}
 
-		intel_dsi_init(dev);
+		ret = intel_dsi_init(dev);
+		if (ret == -EPROBE_DEFER)
+			return ret;
 	} else if (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) {
 		bool found = false;
 
@@ -14795,6 +14800,8 @@  static void intel_setup_outputs(struct drm_device *dev)
 	intel_init_pch_refclk(dev);
 
 	drm_helper_move_panel_connectors_to_head(dev);
+
+	return 0;
 }
 
 static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
@@ -15539,7 +15546,7 @@  fail:
 	drm_modeset_acquire_fini(&ctx);
 }
 
-void intel_modeset_init(struct drm_device *dev)
+int intel_modeset_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
@@ -15564,7 +15571,7 @@  void intel_modeset_init(struct drm_device *dev)
 	intel_init_pm(dev);
 
 	if (INTEL_INFO(dev)->num_pipes == 0)
-		return;
+		return 0;
 
 	/*
 	 * There may be no VBT; and if the BIOS enabled SSC we can
@@ -15632,7 +15639,11 @@  void intel_modeset_init(struct drm_device *dev)
 
 	/* Just disable it once at startup */
 	i915_disable_vga(dev);
-	intel_setup_outputs(dev);
+
+	/* Check if we encountered -EPROBE_DEFER while initializing DSI */
+	ret = intel_setup_outputs(dev);
+	if (ret)
+		return ret;
 
 	drm_modeset_lock_all(dev);
 	intel_modeset_setup_hw_state(dev);
@@ -15667,6 +15678,8 @@  void intel_modeset_init(struct drm_device *dev)
 	 * since the watermark calculation done here will use pstate->fb.
 	 */
 	sanitize_watermarks(dev);
+
+	return 0;
 }
 
 static void intel_enable_pipe_a(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 55aeaf0..4f05b7c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1418,7 +1418,7 @@  int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector);
 int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
 void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
 /* intel_dsi.c */
-void intel_dsi_init(struct drm_device *dev);
+int intel_dsi_init(struct drm_device *dev);
 
 /* intel_dsi_dcs_backlight.c */
 int intel_dsi_dcs_init_backlight_funcs(struct intel_connector *intel_connector);
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index de8e9fb..5c02a3f 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -1422,7 +1422,7 @@  static void intel_dsi_add_properties(struct intel_connector *connector)
 	}
 }
 
-void intel_dsi_init(struct drm_device *dev)
+int intel_dsi_init(struct drm_device *dev)
 {
 	struct intel_dsi *intel_dsi;
 	struct intel_encoder *intel_encoder;
@@ -1433,12 +1433,13 @@  void intel_dsi_init(struct drm_device *dev)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	enum port port;
 	unsigned int i;
+	int ret = 0;
 
 	DRM_DEBUG_KMS("\n");
 
 	/* There is no detection method for MIPI so rely on VBT */
 	if (!intel_bios_is_dsi_present(dev_priv, &port))
-		return;
+		return 0;
 
 	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		dev_priv->mipi_mmio_base = VLV_MIPI_BASE;
@@ -1446,17 +1447,17 @@  void intel_dsi_init(struct drm_device *dev)
 		dev_priv->mipi_mmio_base = BXT_MIPI_BASE;
 	} else {
 		DRM_ERROR("Unsupported Mipi device to reg base");
-		return;
+		return 0;
 	}
 
 	intel_dsi = kzalloc(sizeof(*intel_dsi), GFP_KERNEL);
 	if (!intel_dsi)
-		return;
+		return -ENOMEM;
 
 	intel_connector = intel_connector_alloc();
 	if (!intel_connector) {
 		kfree(intel_dsi);
-		return;
+		return -ENOMEM;
 	}
 
 	intel_encoder = &intel_dsi->base;
@@ -1560,6 +1561,9 @@  void intel_dsi_init(struct drm_device *dev)
 		if (IS_ERR(intel_dsi->gpio_panel)) {
 			DRM_ERROR("Failed to own gpio for panel control\n");
 			intel_dsi->gpio_panel = NULL;
+
+			ret = -EPROBE_DEFER;
+			goto err;
 		}
 	}
 
@@ -1597,14 +1601,20 @@  void intel_dsi_init(struct drm_device *dev)
 	connector->display_info.height_mm = fixed_mode->height_mm;
 
 	intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
-	intel_panel_setup_backlight(connector, INVALID_PIPE);
+	ret = intel_panel_setup_backlight(connector, INVALID_PIPE);
+	if (ret == -ENODEV) {
+		ret = -EPROBE_DEFER;
+		goto err;
+	}
 
 	intel_dsi_add_properties(intel_connector);
 
-	return;
+	return 0;
 
 err:
 	drm_encoder_cleanup(&intel_encoder->base);
 	kfree(intel_dsi);
 	kfree(intel_connector);
+
+	return ret;
 }