{
 }
 
-static int tvc_enable(struct omap_dss_device *dssdev)
-{
-       struct omap_dss_device *src = dssdev->src;
-
-       return src->ops->enable(src);
-}
-
-static void tvc_disable(struct omap_dss_device *dssdev)
-{
-       struct omap_dss_device *src = dssdev->src;
-
-       src->ops->disable(src);
-}
-
 static const struct omap_dss_device_ops tvc_ops = {
        .connect                = tvc_connect,
        .disconnect             = tvc_disconnect,
-
-       .enable                 = tvc_enable,
-       .disable                = tvc_disable,
 };
 
 static int tvc_probe(struct platform_device *pdev)
 static int __exit tvc_remove(struct platform_device *pdev)
 {
        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-       struct omap_dss_device *dssdev = &ddata->dssdev;
 
        omapdss_device_unregister(&ddata->dssdev);
 
-       if (omapdss_device_is_enabled(dssdev))
-               tvc_disable(dssdev);
-
        return 0;
 }
 
 
 {
 }
 
-static int dvic_enable(struct omap_dss_device *dssdev)
-{
-       struct omap_dss_device *src = dssdev->src;
-
-       return src->ops->enable(src);
-}
-
-static void dvic_disable(struct omap_dss_device *dssdev)
-{
-       struct omap_dss_device *src = dssdev->src;
-
-       src->ops->disable(src);
-}
-
 static int dvic_ddc_read(struct i2c_adapter *adapter,
                unsigned char *buf, u16 count, u8 offset)
 {
        .connect        = dvic_connect,
        .disconnect     = dvic_disconnect,
 
-       .enable         = dvic_enable,
-       .disable        = dvic_disable,
-
        .read_edid      = dvic_read_edid,
        .detect         = dvic_detect,
 
 static int __exit dvic_remove(struct platform_device *pdev)
 {
        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-       struct omap_dss_device *dssdev = &ddata->dssdev;
 
        omapdss_device_unregister(&ddata->dssdev);
 
-       if (omapdss_device_is_enabled(dssdev))
-               dvic_disable(dssdev);
-
        i2c_put_adapter(ddata->i2c_adapter);
 
        mutex_destroy(&ddata->hpd_lock);
 
 {
 }
 
-static int hdmic_enable(struct omap_dss_device *dssdev)
-{
-       struct omap_dss_device *src = dssdev->src;
-
-       return src->ops->enable(src);
-}
-
-static void hdmic_disable(struct omap_dss_device *dssdev)
-{
-       struct omap_dss_device *src = dssdev->src;
-
-       src->ops->disable(src);
-}
-
 static bool hdmic_detect(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
        .connect                = hdmic_connect,
        .disconnect             = hdmic_disconnect,
 
-       .enable                 = hdmic_enable,
-       .disable                = hdmic_disable,
-
        .detect                 = hdmic_detect,
        .register_hpd_cb        = hdmic_register_hpd_cb,
        .unregister_hpd_cb      = hdmic_unregister_hpd_cb,
 static int __exit hdmic_remove(struct platform_device *pdev)
 {
        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-       struct omap_dss_device *dssdev = &ddata->dssdev;
 
        omapdss_device_unregister(&ddata->dssdev);
 
-       if (omapdss_device_is_enabled(dssdev))
-               hdmic_disable(dssdev);
-
        return 0;
 }
 
 
        omapdss_device_disconnect(dst, dst->next);
 }
 
-static int opa362_enable(struct omap_dss_device *dssdev)
+static void opa362_enable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
-       int r;
-
-       dev_dbg(dssdev->dev, "enable\n");
-
-       r = src->ops->enable(src);
-       if (r)
-               return r;
 
        if (ddata->enable_gpio)
                gpiod_set_value_cansleep(ddata->enable_gpio, 1);
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-       return 0;
 }
 
 static void opa362_disable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
-
-       dev_dbg(dssdev->dev, "disable\n");
 
        if (ddata->enable_gpio)
                gpiod_set_value_cansleep(ddata->enable_gpio, 0);
-
-       src->ops->disable(src);
-
-       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
 static const struct omap_dss_device_ops opa362_ops = {
                omapdss_device_put(dssdev->next);
        omapdss_device_unregister(&ddata->dssdev);
 
-       WARN_ON(omapdss_device_is_enabled(dssdev));
-       if (omapdss_device_is_enabled(dssdev))
-               opa362_disable(dssdev);
+       opa362_disable(dssdev);
 
        return 0;
 }
 
        omapdss_device_disconnect(dst, dst->next);
 }
 
-static int tfp410_enable(struct omap_dss_device *dssdev)
+static void tfp410_enable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
-       int r;
-
-       r = src->ops->enable(src);
-       if (r)
-               return r;
 
        if (ddata->pd_gpio)
                gpiod_set_value_cansleep(ddata->pd_gpio, 0);
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-       return 0;
 }
 
 static void tfp410_disable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
 
        if (ddata->pd_gpio)
                gpiod_set_value_cansleep(ddata->pd_gpio, 0);
-
-       src->ops->disable(src);
-
-       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
 static const struct omap_dss_device_ops tfp410_ops = {
                omapdss_device_put(dssdev->next);
        omapdss_device_unregister(&ddata->dssdev);
 
-       WARN_ON(omapdss_device_is_enabled(dssdev));
-       if (omapdss_device_is_enabled(dssdev))
-               tfp410_disable(dssdev);
+       tfp410_disable(dssdev);
 
        return 0;
 }
 
        omapdss_device_disconnect(dst, dst->next);
 }
 
-static int tpd_enable(struct omap_dss_device *dssdev)
-{
-       struct omap_dss_device *src = dssdev->src;
-       int r;
-
-       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
-               return 0;
-
-       r = src->ops->enable(src);
-       if (r)
-               return r;
-
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
-
-       return r;
-}
-
-static void tpd_disable(struct omap_dss_device *dssdev)
-{
-       struct omap_dss_device *src = dssdev->src;
-
-       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
-               return;
-
-       src->ops->disable(src);
-
-       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
-}
-
 static bool tpd_detect(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
 static const struct omap_dss_device_ops tpd_ops = {
        .connect                = tpd_connect,
        .disconnect             = tpd_disconnect,
-       .enable                 = tpd_enable,
-       .disable                = tpd_disable,
        .detect                 = tpd_detect,
        .register_hpd_cb        = tpd_register_hpd_cb,
        .unregister_hpd_cb      = tpd_unregister_hpd_cb,
                omapdss_device_put(dssdev->next);
        omapdss_device_unregister(&ddata->dssdev);
 
-       WARN_ON(omapdss_device_is_enabled(dssdev));
-       if (omapdss_device_is_enabled(dssdev))
-               tpd_disable(dssdev);
-
        return 0;
 }
 
 
 {
 }
 
-static int panel_dpi_enable(struct omap_dss_device *dssdev)
+static void panel_dpi_enable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
        int r;
 
-       r = src->ops->enable(src);
-       if (r)
-               return r;
-
        r = regulator_enable(ddata->vcc_supply);
-       if (r) {
-               src->ops->disable(src);
-               return r;
-       }
+       if (r)
+               return;
 
        gpiod_set_value_cansleep(ddata->enable_gpio, 1);
        backlight_enable(ddata->backlight);
-
-       return 0;
 }
 
 static void panel_dpi_disable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
 
        backlight_disable(ddata->backlight);
 
        gpiod_set_value_cansleep(ddata->enable_gpio, 0);
        regulator_disable(ddata->vcc_supply);
-
-       src->ops->disable(src);
 }
 
 static void panel_dpi_get_timings(struct omap_dss_device *dssdev,
 
        if (!ddata->ulps_enabled)
                return 0;
 
-       r = src->ops->enable(src);
-       if (r) {
-               dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
-               goto err1;
-       }
-
+       src->ops->enable(src);
        src->ops->dsi.enable_hs(src, ddata->channel, true);
 
        r = _dsicm_enable_te(ddata, true);
                        enable_irq(gpiod_to_irq(ddata->ext_te_gpio));
                ddata->ulps_enabled = false;
        }
-err1:
+
        dsicm_queue_ulps_work(ddata);
 
        return r;
                goto err_vddi;
        }
 
-       r = src->ops->enable(src);
-       if (r) {
-               dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
-               goto err_vddi;
-       }
+       src->ops->enable(src);
 
        dsicm_hw_reset(ddata);
 
        src->ops->dsi.release_vc(src, ddata->channel);
 }
 
-static int dsicm_enable(struct omap_dss_device *dssdev)
+static void dsicm_enable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
        struct omap_dss_device *src = dssdev->src;
 
        dsicm_bl_power(ddata, true);
 
-       return 0;
+       return;
 err:
-       dev_dbg(&ddata->pdev->dev, "enable failed\n");
+       dev_dbg(&ddata->pdev->dev, "enable failed (%d)\n", r);
        mutex_unlock(&ddata->lock);
-       return r;
 }
 
 static void dsicm_disable(struct omap_dss_device *dssdev)
 
 {
 }
 
-static int lb035q02_enable(struct omap_dss_device *dssdev)
+static void lb035q02_enable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
-       int r;
-
-       r = src->ops->enable(src);
-       if (r)
-               return r;
 
        if (ddata->enable_gpio)
                gpiod_set_value_cansleep(ddata->enable_gpio, 1);
-
-       return 0;
 }
 
 static void lb035q02_disable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
 
        if (ddata->enable_gpio)
                gpiod_set_value_cansleep(ddata->enable_gpio, 0);
-
-       src->ops->disable(src);
 }
 
 static void lb035q02_get_timings(struct omap_dss_device *dssdev,
 
        omapdss_device_unregister(dssdev);
 
-       if (omapdss_device_is_enabled(dssdev))
-               lb035q02_disable(dssdev);
+       lb035q02_disable(dssdev);
 
        return 0;
 }
 
 {
 }
 
-static int nec_8048_enable(struct omap_dss_device *dssdev)
+static void nec_8048_enable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
-       int r;
-
-       r = src->ops->enable(src);
-       if (r)
-               return r;
 
        gpiod_set_value_cansleep(ddata->res_gpio, 1);
-
-       return 0;
 }
 
 static void nec_8048_disable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
 
        gpiod_set_value_cansleep(ddata->res_gpio, 0);
-
-       src->ops->disable(src);
 }
 
 static void nec_8048_get_timings(struct omap_dss_device *dssdev,
 
        omapdss_device_unregister(dssdev);
 
-       if (omapdss_device_is_enabled(dssdev))
-               nec_8048_disable(dssdev);
+       nec_8048_disable(dssdev);
 
        return 0;
 }
 
 {
 }
 
-static int sharp_ls_enable(struct omap_dss_device *dssdev)
+static void sharp_ls_pre_enable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
        int r;
 
        if (ddata->vcc) {
                r = regulator_enable(ddata->vcc);
-               if (r != 0)
-                       return r;
+               if (r)
+                       dev_err(dssdev->dev, "%s: failed to enable regulator\n",
+                               __func__);
        }
+}
 
-       r = src->ops->enable(src);
-       if (r) {
-               regulator_disable(ddata->vcc);
-               return r;
-       }
+static void sharp_ls_enable(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata = to_panel_data(dssdev);
 
        /* wait couple of vsyncs until enabling the LCD */
        msleep(50);
 
        if (ddata->ini_gpio)
                gpiod_set_value_cansleep(ddata->ini_gpio, 1);
-
-       return 0;
 }
 
 static void sharp_ls_disable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
 
        if (ddata->ini_gpio)
                gpiod_set_value_cansleep(ddata->ini_gpio, 0);
                gpiod_set_value_cansleep(ddata->resb_gpio, 0);
 
        /* wait at least 5 vsyncs after disabling the LCD */
-
        msleep(100);
+}
 
-       src->ops->disable(src);
+static void sharp_ls_post_disable(struct omap_dss_device *dssdev)
+{
+       struct panel_drv_data *ddata = to_panel_data(dssdev);
 
        if (ddata->vcc)
                regulator_disable(ddata->vcc);
        .connect        = sharp_ls_connect,
        .disconnect     = sharp_ls_disconnect,
 
+       .pre_enable     = sharp_ls_pre_enable,
        .enable         = sharp_ls_enable,
        .disable        = sharp_ls_disable,
+       .post_disable   = sharp_ls_post_disable,
 
        .get_timings    = sharp_ls_get_timings,
 };
 
        omapdss_device_unregister(dssdev);
 
-       if (omapdss_device_is_enabled(dssdev))
+       if (omapdss_device_is_enabled(dssdev)) {
                sharp_ls_disable(dssdev);
+               sharp_ls_post_disable(dssdev);
+       }
 
        return 0;
 }
 
 static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
-       int r;
 
        dev_dbg(&ddata->spi->dev, "%s\n", __func__);
 
-       r = src->ops->enable(src);
-       if (r) {
-               pr_err("%s sdi enable failed\n", __func__);
-               return r;
-       }
-
        /*FIXME tweak me */
        msleep(50);
 
 static void acx565akm_panel_power_off(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
 
        dev_dbg(dssdev->dev, "%s\n", __func__);
 
 
        /* FIXME need to tweak this delay */
        msleep(100);
-
-       src->ops->disable(src);
 }
 
-static int acx565akm_enable(struct omap_dss_device *dssdev)
+static void acx565akm_enable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       int r;
 
        mutex_lock(&ddata->mutex);
-       r = acx565akm_panel_power_on(dssdev);
+       acx565akm_panel_power_on(dssdev);
        mutex_unlock(&ddata->mutex);
-
-       return r;
 }
 
 static void acx565akm_disable(struct omap_dss_device *dssdev)
 
 {
 }
 
-static int td028ttec1_panel_enable(struct omap_dss_device *dssdev)
+static void td028ttec1_panel_enable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
-       int r;
-
-       r = src->ops->enable(src);
-       if (r)
-               return r;
+       int r = 0;
 
-       dev_dbg(dssdev->dev, "td028ttec1_panel_enable() - state %d\n",
-               dssdev->state);
+       dev_dbg(dssdev->dev, "%s: state %d\n", __func__, dssdev->state);
 
        /* three times command zero */
        r |= jbt_ret_write_0(ddata, 0x00);
        usleep_range(1000, 2000);
 
        if (r) {
-               dev_warn(dssdev->dev, "transfer error\n");
-               return -EIO;
+               dev_warn(dssdev->dev, "%s: transfer error\n", __func__);
+               return;
        }
 
        /* deep standby out */
 
        r |= jbt_ret_write_0(ddata, JBT_REG_DISPLAY_ON);
 
-       return r ? -EIO : 0;
+       if (r)
+               dev_err(dssdev->dev, "%s: write error\n", __func__);
 }
 
 static void td028ttec1_panel_disable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
 
        dev_dbg(dssdev->dev, "td028ttec1_panel_disable()\n");
 
        jbt_reg_write_2(ddata, JBT_REG_OUTPUT_CONTROL, 0x8002);
        jbt_ret_write_0(ddata, JBT_REG_SLEEP_IN);
        jbt_reg_write_1(ddata, JBT_REG_POWER_ON_OFF, 0x00);
-
-       src->ops->disable(src);
 }
 
 static void td028ttec1_panel_get_timings(struct omap_dss_device *dssdev,
 
        omapdss_device_unregister(dssdev);
 
-       if (omapdss_device_is_enabled(dssdev))
-               td028ttec1_panel_disable(dssdev);
+       td028ttec1_panel_disable(dssdev);
 
        return 0;
 }
 
 {
 }
 
-static int tpo_td043_enable(struct omap_dss_device *dssdev)
+static void tpo_td043_enable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
        int r;
 
-       r = src->ops->enable(src);
-       if (r)
-               return r;
-
        /*
         * If we are resuming from system suspend, SPI clocks might not be
         * enabled yet, so we'll program the LCD from SPI PM resume callback.
        if (!ddata->spi_suspended) {
                r = tpo_td043_power_on(ddata);
                if (r) {
-                       src->ops->disable(src);
-                       return r;
+                       dev_err(&ddata->spi->dev, "%s: power on failed (%d)\n",
+                               __func__, r);
+                       return;
                }
        }
-
-       return 0;
 }
 
 static void tpo_td043_disable(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *src = dssdev->src;
-
-       src->ops->disable(src);
 
        if (!ddata->spi_suspended)
                tpo_td043_power_off(ddata);
 
 }
 
 /*
- * Search for the next device starting at @from. The type argument specfies
- * which device types to consider when searching. Searching for multiple types
- * is supported by and'ing their type flags. Release the reference to the @from
- * device, and acquire a reference to the returned device if found.
+ * Search for the next output device starting at @from. Release the reference to
+ * the @from device, and acquire a reference to the returned device if found.
  */
-struct omap_dss_device *omapdss_device_get_next(struct omap_dss_device *from,
-                                               enum omap_dss_device_type type)
+struct omap_dss_device *omapdss_device_next_output(struct omap_dss_device *from)
 {
        struct omap_dss_device *dssdev;
        struct list_head *list;
                        goto done;
                }
 
-               /*
-                * Accept display entities if the display type is requested,
-                * and output entities if the output type is requested.
-                */
-               if ((type & OMAP_DSS_DEVICE_TYPE_DISPLAY) &&
-                   !dssdev->output_type)
-                       goto done;
-               if ((type & OMAP_DSS_DEVICE_TYPE_OUTPUT) && dssdev->id &&
-                   dssdev->next)
+               if (dssdev->id && dssdev->next)
                        goto done;
        }
 
        mutex_unlock(&omapdss_devices_lock);
        return dssdev;
 }
-EXPORT_SYMBOL(omapdss_device_get_next);
+EXPORT_SYMBOL(omapdss_device_next_output);
 
 static bool omapdss_device_is_connected(struct omap_dss_device *dssdev)
 {
 }
 EXPORT_SYMBOL_GPL(omapdss_device_disconnect);
 
+void omapdss_device_pre_enable(struct omap_dss_device *dssdev)
+{
+       if (!dssdev)
+               return;
+
+       omapdss_device_pre_enable(dssdev->next);
+
+       if (dssdev->ops->pre_enable)
+               dssdev->ops->pre_enable(dssdev);
+}
+EXPORT_SYMBOL_GPL(omapdss_device_pre_enable);
+
+void omapdss_device_enable(struct omap_dss_device *dssdev)
+{
+       if (!dssdev)
+               return;
+
+       if (dssdev->ops->enable)
+               dssdev->ops->enable(dssdev);
+
+       omapdss_device_enable(dssdev->next);
+
+       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+}
+EXPORT_SYMBOL_GPL(omapdss_device_enable);
+
+void omapdss_device_disable(struct omap_dss_device *dssdev)
+{
+       if (!dssdev)
+               return;
+
+       omapdss_device_disable(dssdev->next);
+
+       if (dssdev->ops->disable)
+               dssdev->ops->disable(dssdev);
+}
+EXPORT_SYMBOL_GPL(omapdss_device_disable);
+
+void omapdss_device_post_disable(struct omap_dss_device *dssdev)
+{
+       if (!dssdev)
+               return;
+
+       if (dssdev->ops->post_disable)
+               dssdev->ops->post_disable(dssdev);
+
+       omapdss_device_post_disable(dssdev->next);
+
+       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+EXPORT_SYMBOL_GPL(omapdss_device_post_disable);
+
 /* -----------------------------------------------------------------------------
  * Components Handling
  */
 
        dss_mgr_set_lcd_config(&dpi->output, &dpi->mgr_config);
 }
 
-static int dpi_display_enable(struct omap_dss_device *dssdev)
+static void dpi_display_enable(struct omap_dss_device *dssdev)
 {
        struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
        struct omap_dss_device *out = &dpi->output;
 
        mutex_unlock(&dpi->lock);
 
-       return 0;
+       return;
 
 err_mgr_enable:
 err_set_mode:
                regulator_disable(dpi->vdds_dsi_reg);
 err_reg_enable:
        mutex_unlock(&dpi->lock);
-       return r;
 }
 
 static void dpi_display_disable(struct omap_dss_device *dssdev)
 
        dsi_pll_uninit(dsi, disconnect_lanes);
 }
 
-static int dsi_display_enable(struct omap_dss_device *dssdev)
+static void dsi_display_enable(struct omap_dss_device *dssdev)
 {
        struct dsi_data *dsi = to_dsi_data(dssdev);
-       int r = 0;
+       int r;
 
        DSSDBG("dsi_display_enable\n");
 
 
        mutex_unlock(&dsi->lock);
 
-       return 0;
+       return;
 
 err_init_dsi:
        dsi_runtime_put(dsi);
 err_get_dsi:
        mutex_unlock(&dsi->lock);
        DSSDBG("dsi_display_enable FAILED\n");
-       return r;
 }
 
 static void dsi_display_disable(struct omap_dss_device *dssdev,
 
 
        DSSDBG("shutdown\n");
 
-       for_each_dss_display(dssdev) {
+       for_each_dss_output(dssdev) {
                if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
                        dssdev->ops->disable(dssdev);
        }
 
        hdmi_wp_audio_enable(&hd->wp, false);
 }
 
-static int hdmi_display_enable(struct omap_dss_device *dssdev)
+static void hdmi_display_enable(struct omap_dss_device *dssdev)
 {
        struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
        unsigned long flags;
-       int r = 0;
+       int r;
 
        DSSDBG("ENTER hdmi_display_enable\n");
 
        r = hdmi_power_on_full(hdmi);
        if (r) {
                DSSERR("failed to power on device\n");
-               goto err0;
+               goto done;
        }
 
        if (hdmi->audio_configured) {
        hdmi->display_enabled = true;
        spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
 
+done:
        mutex_unlock(&hdmi->lock);
-       return 0;
-
-err0:
-       mutex_unlock(&hdmi->lock);
-       return r;
 }
 
 static void hdmi_display_disable(struct omap_dss_device *dssdev)
 
        REG_FLD_MOD(hd->wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode, 3, 2);
 }
 
-static int hdmi_display_enable(struct omap_dss_device *dssdev)
+static void hdmi_display_enable(struct omap_dss_device *dssdev)
 {
        struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev);
        unsigned long flags;
-       int r = 0;
+       int r;
 
        DSSDBG("ENTER hdmi_display_enable\n");
 
        r = hdmi_power_on_full(hdmi);
        if (r) {
                DSSERR("failed to power on device\n");
-               goto err0;
+               goto done;
        }
 
        if (hdmi->audio_configured) {
        hdmi->display_enabled = true;
        spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags);
 
+done:
        mutex_unlock(&hdmi->lock);
-       return 0;
-
-err0:
-       mutex_unlock(&hdmi->lock);
-       return r;
 }
 
 static void hdmi_display_disable(struct omap_dss_device *dssdev)
 
        void (*disconnect)(struct omap_dss_device *dssdev,
                        struct omap_dss_device *dst);
 
-       int (*enable)(struct omap_dss_device *dssdev);
+       void (*pre_enable)(struct omap_dss_device *dssdev);
+       void (*enable)(struct omap_dss_device *dssdev);
        void (*disable)(struct omap_dss_device *dssdev);
+       void (*post_disable)(struct omap_dss_device *dssdev);
 
        int (*check_timings)(struct omap_dss_device *dssdev,
                             struct videomode *vm);
        OMAP_DSS_DEVICE_OP_EDID = BIT(2),
 };
 
-enum omap_dss_device_type {
-       OMAP_DSS_DEVICE_TYPE_OUTPUT = (1 << 0),
-       OMAP_DSS_DEVICE_TYPE_DISPLAY = (1 << 1),
-};
-
 struct omap_dss_device {
        struct device *dev;
 
        return !!omapdss_get_dss();
 }
 
-#define for_each_dss_display(d) \
-       while ((d = omapdss_device_get_next(d, OMAP_DSS_DEVICE_TYPE_DISPLAY)) != NULL)
 void omapdss_display_init(struct omap_dss_device *dssdev);
 struct omap_dss_device *omapdss_display_get(struct omap_dss_device *output);
 
 void omapdss_device_put(struct omap_dss_device *dssdev);
 struct omap_dss_device *omapdss_find_device_by_port(struct device_node *src,
                                                    unsigned int port);
-struct omap_dss_device *omapdss_device_get_next(struct omap_dss_device *from,
-                                               enum omap_dss_device_type type);
 int omapdss_device_connect(struct dss_device *dss,
                           struct omap_dss_device *src,
                           struct omap_dss_device *dst);
 void omapdss_device_disconnect(struct omap_dss_device *src,
                               struct omap_dss_device *dst);
+void omapdss_device_pre_enable(struct omap_dss_device *dssdev);
+void omapdss_device_enable(struct omap_dss_device *dssdev);
+void omapdss_device_disable(struct omap_dss_device *dssdev);
+void omapdss_device_post_disable(struct omap_dss_device *dssdev);
 
 int omap_dss_get_num_overlay_managers(void);
 
 int omap_dss_get_num_overlays(void);
 
 #define for_each_dss_output(d) \
-       while ((d = omapdss_device_get_next(d, OMAP_DSS_DEVICE_TYPE_OUTPUT)) != NULL)
+       while ((d = omapdss_device_next_output(d)) != NULL)
+struct omap_dss_device *omapdss_device_next_output(struct omap_dss_device *from);
 int omapdss_output_validate(struct omap_dss_device *out);
 
 typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
 
        dss_mgr_set_lcd_config(&sdi->output, &sdi->mgr_config);
 }
 
-static int sdi_display_enable(struct omap_dss_device *dssdev)
+static void sdi_display_enable(struct omap_dss_device *dssdev)
 {
        struct sdi_device *sdi = dssdev_to_sdi(dssdev);
        struct dispc_clock_info dispc_cinfo;
 
        r = regulator_enable(sdi->vdds_sdi_reg);
        if (r)
-               goto err_reg_enable;
+               return;
 
        r = dispc_runtime_get(sdi->dss->dispc);
        if (r)
        if (r)
                goto err_mgr_enable;
 
-       return 0;
+       return;
 
 err_mgr_enable:
        dss_sdi_disable(sdi->dss);
        dispc_runtime_put(sdi->dss->dispc);
 err_get_dispc:
        regulator_disable(sdi->vdds_sdi_reg);
-err_reg_enable:
-       return r;
 }
 
 static void sdi_display_disable(struct omap_dss_device *dssdev)
 
        venc_runtime_put(venc);
 }
 
-static int venc_display_enable(struct omap_dss_device *dssdev)
+static void venc_display_enable(struct omap_dss_device *dssdev)
 {
        struct venc_device *venc = dssdev_to_venc(dssdev);
-       int r;
 
        DSSDBG("venc_display_enable\n");
 
        mutex_lock(&venc->venc_lock);
 
-       r = venc_power_on(venc);
-       if (r)
-               goto err0;
-
-       mutex_unlock(&venc->venc_lock);
+       venc_power_on(venc);
 
-       return 0;
-err0:
        mutex_unlock(&venc->venc_lock);
-       return r;
 }
 
 static void venc_display_disable(struct omap_dss_device *dssdev)
 
 static void omap_encoder_disable(struct drm_encoder *encoder)
 {
        struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-       struct omap_dss_device *dssdev = omap_encoder->display;
+       struct omap_dss_device *dssdev = omap_encoder->output;
        struct drm_device *dev = encoder->dev;
 
        dev_dbg(dev->dev, "disable(%s)\n", dssdev->name);
 
-       dssdev->ops->disable(dssdev);
+       /*
+        * Disable the chain of external devices, starting at the one at the
+        * internal encoder's output.
+        */
+       omapdss_device_disable(dssdev->next);
+
+       /*
+        * Disable the internal encoder. This will disable the DSS output. The
+        * DSI is treated as an exception as DSI pipelines still use the legacy
+        * flow where the pipeline output controls the encoder.
+        */
+       if (dssdev->output_type != OMAP_DISPLAY_TYPE_DSI) {
+               dssdev->ops->disable(dssdev);
+               dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+       }
 
-       dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+       /*
+        * Perform the post-disable operations on the chain of external devices
+        * to complete the display pipeline disable.
+        */
+       omapdss_device_post_disable(dssdev->next);
 }
 
 static void omap_encoder_enable(struct drm_encoder *encoder)
 {
        struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-       struct omap_dss_device *dssdev = omap_encoder->display;
+       struct omap_dss_device *dssdev = omap_encoder->output;
        struct drm_device *dev = encoder->dev;
-       int r;
 
        dev_dbg(dev->dev, "enable(%s)\n", dssdev->name);
 
-       r = dssdev->ops->enable(dssdev);
-       if (r) {
-               dev_err(dev->dev, "Failed to enable display '%s': %d\n",
-                       dssdev->name, r);
-               return;
+       /* Prepare the chain of external devices for pipeline enable. */
+       omapdss_device_pre_enable(dssdev->next);
+
+       /*
+        * Enable the internal encoder. This will enable the DSS output. The
+        * DSI is treated as an exception as DSI pipelines still use the legacy
+        * flow where the pipeline output controls the encoder.
+        */
+       if (dssdev->output_type != OMAP_DISPLAY_TYPE_DSI) {
+               dssdev->ops->enable(dssdev);
+               dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
        }
 
-       dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+       /*
+        * Enable the chain of external devices, starting at the one at the
+        * internal encoder's output.
+        */
+       omapdss_device_enable(dssdev->next);
 }
 
 static int omap_encoder_atomic_check(struct drm_encoder *encoder,