drm: omapdrm: displays: Get panel source at connect time
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Sun, 11 Feb 2018 13:07:40 +0000 (15:07 +0200)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Thu, 1 Mar 2018 07:18:18 +0000 (09:18 +0200)
The connector drivers need a handle to the source they are connected to
in order to control the source.

All drivers get that handle at probe time, resulting in probe deferral
when the source hasn't been probed yet. However they don't need the
handle until their connect handler is called.

Move retrieval of the source handle to the connect handler to avoid
probe deferrals.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
drivers/gpu/drm/omapdrm/displays/panel-dpi.c
drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c
drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c
drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c
drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c
drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c
drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c

index bae8fd5357eac38367f45c044f142118bd68377d..6cbf570d67273927a5a1e095faf89d062a32cc02 100644 (file)
@@ -38,16 +38,25 @@ struct panel_drv_data {
 static int panel_dpi_connect(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
+       struct omap_dss_device *in;
        int r;
 
        if (omapdss_device_is_connected(dssdev))
                return 0;
 
+       in = omapdss_of_find_source_for_first_ep(dssdev->dev->of_node);
+       if (IS_ERR(in)) {
+               dev_err(dssdev->dev, "failed to find video source\n");
+               return PTR_ERR(in);
+       }
+
        r = in->ops.dpi->connect(in, dssdev);
-       if (r)
+       if (r) {
+               omap_dss_put_device(in);
                return r;
+       }
 
+       ddata->in = in;
        return 0;
 }
 
@@ -60,6 +69,9 @@ static void panel_dpi_disconnect(struct omap_dss_device *dssdev)
                return;
 
        in->ops.dpi->disconnect(in, dssdev);
+
+       omap_dss_put_device(in);
+       ddata->in = NULL;
 }
 
 static int panel_dpi_enable(struct omap_dss_device *dssdev)
@@ -157,7 +169,6 @@ static int panel_dpi_probe_of(struct platform_device *pdev)
 {
        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
        struct device_node *node = pdev->dev.of_node;
-       struct omap_dss_device *in;
        int r;
        struct display_timing timing;
        struct gpio_desc *gpio;
@@ -195,14 +206,6 @@ static int panel_dpi_probe_of(struct platform_device *pdev)
 
        videomode_from_timing(&timing, &ddata->vm);
 
-       in = omapdss_of_find_source_for_first_ep(node);
-       if (IS_ERR(in)) {
-               dev_err(&pdev->dev, "failed to find video source\n");
-               return PTR_ERR(in);
-       }
-
-       ddata->in = in;
-
        return 0;
 }
 
@@ -232,29 +235,22 @@ static int panel_dpi_probe(struct platform_device *pdev)
        r = omapdss_register_display(dssdev);
        if (r) {
                dev_err(&pdev->dev, "Failed to register panel\n");
-               goto err_reg;
+               return r;
        }
 
        return 0;
-
-err_reg:
-       omap_dss_put_device(ddata->in);
-       return r;
 }
 
 static int __exit panel_dpi_remove(struct platform_device *pdev)
 {
        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
        struct omap_dss_device *dssdev = &ddata->dssdev;
-       struct omap_dss_device *in = ddata->in;
 
        omapdss_unregister_display(dssdev);
 
        panel_dpi_disable(dssdev);
        panel_dpi_disconnect(dssdev);
 
-       omap_dss_put_device(in);
-
        return 0;
 }
 
index 002082ecbbbcae85a33c33c8bfbee6c35940ae6d..f960e55d64eab351c99442353af3c4c74640b895 100644 (file)
@@ -759,17 +759,23 @@ static int dsicm_panel_reset(struct panel_drv_data *ddata)
 static int dsicm_connect(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
        struct device *dev = &ddata->pdev->dev;
+       struct omap_dss_device *in;
        int r;
 
        if (omapdss_device_is_connected(dssdev))
                return 0;
 
+       in = omapdss_of_find_source_for_first_ep(dssdev->dev->of_node);
+       if (IS_ERR(in)) {
+               dev_err(dssdev->dev, "failed to find video source\n");
+               return PTR_ERR(in);
+       }
+
        r = in->ops.dsi->connect(in, dssdev);
        if (r) {
                dev_err(dev, "Failed to connect to video source\n");
-               return r;
+               goto err_connect;
        }
 
        r = in->ops.dsi->request_vc(ddata->in, &ddata->channel);
@@ -784,12 +790,15 @@ static int dsicm_connect(struct omap_dss_device *dssdev)
                goto err_vc_id;
        }
 
+       ddata->in = in;
        return 0;
 
 err_vc_id:
        in->ops.dsi->release_vc(ddata->in, ddata->channel);
 err_req_vc:
        in->ops.dsi->disconnect(in, dssdev);
+err_connect:
+       omap_dss_put_device(in);
        return r;
 }
 
@@ -803,6 +812,9 @@ static void dsicm_disconnect(struct omap_dss_device *dssdev)
 
        in->ops.dsi->release_vc(in, ddata->channel);
        in->ops.dsi->disconnect(in, dssdev);
+
+       omap_dss_put_device(in);
+       ddata->in = NULL;
 }
 
 static int dsicm_enable(struct omap_dss_device *dssdev)
@@ -1223,7 +1235,6 @@ static int dsicm_probe_of(struct platform_device *pdev)
        struct device_node *node = pdev->dev.of_node;
        struct device_node *backlight;
        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-       struct omap_dss_device *in;
        struct display_timing timing;
        int err;
 
@@ -1259,12 +1270,6 @@ static int dsicm_probe_of(struct platform_device *pdev)
        ddata->height_mm = 0;
        of_property_read_u32(node, "height-mm", &ddata->height_mm);
 
-       in = omapdss_of_find_source_for_first_ep(node);
-       if (IS_ERR(in)) {
-               dev_err(&pdev->dev, "failed to find video source\n");
-               return PTR_ERR(in);
-       }
-
        ddata->vpnl = devm_regulator_get_optional(&pdev->dev, "vpnl");
        if (IS_ERR(ddata->vpnl)) {
                err = PTR_ERR(ddata->vpnl);
@@ -1281,8 +1286,6 @@ static int dsicm_probe_of(struct platform_device *pdev)
                ddata->vddi = NULL;
        }
 
-       ddata->in = in;
-
        backlight = of_parse_phandle(node, "backlight", 0);
        if (backlight) {
                ddata->extbldev = of_find_backlight_by_node(backlight);
@@ -1421,8 +1424,6 @@ static int __exit dsicm_remove(struct platform_device *pdev)
        if (ddata->extbldev)
                put_device(&ddata->extbldev->dev);
 
-       omap_dss_put_device(ddata->in);
-
        dsicm_cancel_ulps_work(ddata);
        destroy_workqueue(ddata->workqueue);
 
index 8cb958c0c39d56b83cf3d472ad78a5cb925f4e10..75419709944012834cefbc8e16dbbd6ff77bc247 100644 (file)
@@ -119,18 +119,27 @@ static void init_lb035q02_panel(struct spi_device *spi)
 static int lb035q02_connect(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
+       struct omap_dss_device *in;
        int r;
 
        if (omapdss_device_is_connected(dssdev))
                return 0;
 
+       in = omapdss_of_find_source_for_first_ep(dssdev->dev->of_node);
+       if (IS_ERR(in)) {
+               dev_err(dssdev->dev, "failed to find video source\n");
+               return PTR_ERR(in);
+       }
+
        r = in->ops.dpi->connect(in, dssdev);
-       if (r)
+       if (r) {
+               omap_dss_put_device(in);
                return r;
+       }
 
        init_lb035q02_panel(ddata->spi);
 
+       ddata->in = in;
        return 0;
 }
 
@@ -143,6 +152,9 @@ static void lb035q02_disconnect(struct omap_dss_device *dssdev)
                return;
 
        in->ops.dpi->disconnect(in, dssdev);
+
+       omap_dss_put_device(in);
+       ddata->in = NULL;
 }
 
 static int lb035q02_enable(struct omap_dss_device *dssdev)
@@ -230,9 +242,7 @@ static struct omap_dss_driver lb035q02_ops = {
 
 static int lb035q02_probe_of(struct spi_device *spi)
 {
-       struct device_node *node = spi->dev.of_node;
        struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-       struct omap_dss_device *in;
        struct gpio_desc *gpio;
 
        gpio = devm_gpiod_get(&spi->dev, "enable", GPIOD_OUT_LOW);
@@ -243,14 +253,6 @@ static int lb035q02_probe_of(struct spi_device *spi)
 
        ddata->enable_gpio = gpio;
 
-       in = omapdss_of_find_source_for_first_ep(node);
-       if (IS_ERR(in)) {
-               dev_err(&spi->dev, "failed to find video source\n");
-               return PTR_ERR(in);
-       }
-
-       ddata->in = in;
-
        return 0;
 }
 
@@ -284,29 +286,22 @@ static int lb035q02_panel_spi_probe(struct spi_device *spi)
        r = omapdss_register_display(dssdev);
        if (r) {
                dev_err(&spi->dev, "Failed to register panel\n");
-               goto err_reg;
+               return r;
        }
 
        return 0;
-
-err_reg:
-       omap_dss_put_device(ddata->in);
-       return r;
 }
 
 static int lb035q02_panel_spi_remove(struct spi_device *spi)
 {
        struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
        struct omap_dss_device *dssdev = &ddata->dssdev;
-       struct omap_dss_device *in = ddata->in;
 
        omapdss_unregister_display(dssdev);
 
        lb035q02_disable(dssdev);
        lb035q02_disconnect(dssdev);
 
-       omap_dss_put_device(in);
-
        return 0;
 }
 
index 3ab4b249e74b341d8e61b55ec818e04fdfcb1345..9a3b27fa5cb57ae1cbaab63a2b99226a7f771701 100644 (file)
@@ -115,16 +115,25 @@ static int init_nec_8048_wvga_lcd(struct spi_device *spi)
 static int nec_8048_connect(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
+       struct omap_dss_device *in;
        int r;
 
        if (omapdss_device_is_connected(dssdev))
                return 0;
 
+       in = omapdss_of_find_source_for_first_ep(dssdev->dev->of_node);
+       if (IS_ERR(in)) {
+               dev_err(dssdev->dev, "failed to find video source\n");
+               return PTR_ERR(in);
+       }
+
        r = in->ops.dpi->connect(in, dssdev);
-       if (r)
+       if (r) {
+               omap_dss_put_device(in);
                return r;
+       }
 
+       ddata->in = in;
        return 0;
 }
 
@@ -137,6 +146,9 @@ static void nec_8048_disconnect(struct omap_dss_device *dssdev)
                return;
 
        in->ops.dpi->disconnect(in, dssdev);
+
+       omap_dss_put_device(in);
+       ddata->in = NULL;
 }
 
 static int nec_8048_enable(struct omap_dss_device *dssdev)
@@ -226,7 +238,6 @@ static int nec_8048_probe_of(struct spi_device *spi)
 {
        struct device_node *node = spi->dev.of_node;
        struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-       struct omap_dss_device *in;
        int gpio;
 
        gpio = of_get_named_gpio(node, "reset-gpios", 0);
@@ -239,14 +250,6 @@ static int nec_8048_probe_of(struct spi_device *spi)
        /* XXX the panel spec doesn't mention any QVGA pin?? */
        ddata->qvga_gpio = -ENOENT;
 
-       in = omapdss_of_find_source_for_first_ep(node);
-       if (IS_ERR(in)) {
-               dev_err(&spi->dev, "failed to find video source\n");
-               return PTR_ERR(in);
-       }
-
-       ddata->in = in;
-
        return 0;
 }
 
@@ -285,14 +288,14 @@ static int nec_8048_probe(struct spi_device *spi)
                r = devm_gpio_request_one(&spi->dev, ddata->qvga_gpio,
                                GPIOF_OUT_INIT_HIGH, "lcd QVGA");
                if (r)
-                       goto err_gpio;
+                       return r;
        }
 
        if (gpio_is_valid(ddata->res_gpio)) {
                r = devm_gpio_request_one(&spi->dev, ddata->res_gpio,
                                GPIOF_OUT_INIT_LOW, "lcd RES");
                if (r)
-                       goto err_gpio;
+                       return r;
        }
 
        ddata->vm = nec_8048_panel_vm;
@@ -307,22 +310,16 @@ static int nec_8048_probe(struct spi_device *spi)
        r = omapdss_register_display(dssdev);
        if (r) {
                dev_err(&spi->dev, "Failed to register panel\n");
-               goto err_reg;
+               return r;
        }
 
        return 0;
-
-err_reg:
-err_gpio:
-       omap_dss_put_device(ddata->in);
-       return r;
 }
 
 static int nec_8048_remove(struct spi_device *spi)
 {
        struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
        struct omap_dss_device *dssdev = &ddata->dssdev;
-       struct omap_dss_device *in = ddata->in;
 
        dev_dbg(&ddata->spi->dev, "%s\n", __func__);
 
@@ -331,8 +328,6 @@ static int nec_8048_remove(struct spi_device *spi)
        nec_8048_disable(dssdev);
        nec_8048_disconnect(dssdev);
 
-       omap_dss_put_device(in);
-
        return 0;
 }
 
index 124867e35e4b8eaec0761be23527acdb876367ff..bb5b680cabfedc1c74f91e991aedf132199abf26 100644 (file)
@@ -61,16 +61,25 @@ static const struct videomode sharp_ls_vm = {
 static int sharp_ls_connect(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
+       struct omap_dss_device *in;
        int r;
 
        if (omapdss_device_is_connected(dssdev))
                return 0;
 
+       in = omapdss_of_find_source_for_first_ep(dssdev->dev->of_node);
+       if (IS_ERR(in)) {
+               dev_err(dssdev->dev, "failed to find video source\n");
+               return PTR_ERR(in);
+       }
+
        r = in->ops.dpi->connect(in, dssdev);
-       if (r)
+       if (r) {
+               omap_dss_put_device(in);
                return r;
+       }
 
+       ddata->in = in;
        return 0;
 }
 
@@ -83,6 +92,9 @@ static void sharp_ls_disconnect(struct omap_dss_device *dssdev)
                return;
 
        in->ops.dpi->disconnect(in, dssdev);
+
+       omap_dss_put_device(in);
+       ddata->in = NULL;
 }
 
 static int sharp_ls_enable(struct omap_dss_device *dssdev)
@@ -210,8 +222,6 @@ static  int sharp_ls_get_gpio_of(struct device *dev, int index, int val,
 static int sharp_ls_probe_of(struct platform_device *pdev)
 {
        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
-       struct device_node *node = pdev->dev.of_node;
-       struct omap_dss_device *in;
        int r;
 
        ddata->vcc = devm_regulator_get(&pdev->dev, "envdd");
@@ -245,14 +255,6 @@ static int sharp_ls_probe_of(struct platform_device *pdev)
        if (r)
                return r;
 
-       in = omapdss_of_find_source_for_first_ep(node);
-       if (IS_ERR(in)) {
-               dev_err(&pdev->dev, "failed to find video source\n");
-               return PTR_ERR(in);
-       }
-
-       ddata->in = in;
-
        return 0;
 }
 
@@ -284,29 +286,22 @@ static int sharp_ls_probe(struct platform_device *pdev)
        r = omapdss_register_display(dssdev);
        if (r) {
                dev_err(&pdev->dev, "Failed to register panel\n");
-               goto err_reg;
+               return r;
        }
 
        return 0;
-
-err_reg:
-       omap_dss_put_device(ddata->in);
-       return r;
 }
 
 static int __exit sharp_ls_remove(struct platform_device *pdev)
 {
        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
        struct omap_dss_device *dssdev = &ddata->dssdev;
-       struct omap_dss_device *in = ddata->in;
 
        omapdss_unregister_display(dssdev);
 
        sharp_ls_disable(dssdev);
        sharp_ls_disconnect(dssdev);
 
-       omap_dss_put_device(in);
-
        return 0;
 }
 
index cc5e9a68726aa1d3bf7df523317d6e9a4a7806d4..c4bb33a247d0d63b71007186e419d025607e330d 100644 (file)
@@ -510,16 +510,25 @@ static const struct attribute_group bldev_attr_group = {
 static int acx565akm_connect(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
+       struct omap_dss_device *in;
        int r;
 
        if (omapdss_device_is_connected(dssdev))
                return 0;
 
+       in = omapdss_of_find_source_for_first_ep(dssdev->dev->of_node);
+       if (IS_ERR(in)) {
+               dev_err(dssdev->dev, "failed to find video source\n");
+               return PTR_ERR(in);
+       }
+
        r = in->ops.sdi->connect(in, dssdev);
-       if (r)
+       if (r) {
+               omap_dss_put_device(in);
                return r;
+       }
 
+       ddata->in = in;
        return 0;
 }
 
@@ -532,6 +541,9 @@ static void acx565akm_disconnect(struct omap_dss_device *dssdev)
                return;
 
        in->ops.sdi->disconnect(in, dssdev);
+
+       omap_dss_put_device(in);
+       ddata->in = NULL;
 }
 
 static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
@@ -700,12 +712,6 @@ static int acx565akm_probe_of(struct spi_device *spi)
 
        ddata->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0);
 
-       ddata->in = omapdss_of_find_source_for_first_ep(np);
-       if (IS_ERR(ddata->in)) {
-               dev_err(&spi->dev, "failed to find video source\n");
-               return PTR_ERR(ddata->in);
-       }
-
        return 0;
 }
 
@@ -823,7 +829,6 @@ err_sysfs:
 err_reg_bl:
 err_detect:
 err_gpio:
-       omap_dss_put_device(ddata->in);
        return r;
 }
 
@@ -831,7 +836,6 @@ static int acx565akm_remove(struct spi_device *spi)
 {
        struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
        struct omap_dss_device *dssdev = &ddata->dssdev;
-       struct omap_dss_device *in = ddata->in;
 
        dev_dbg(&ddata->spi->dev, "%s\n", __func__);
 
@@ -843,8 +847,6 @@ static int acx565akm_remove(struct spi_device *spi)
        acx565akm_disable(dssdev);
        acx565akm_disconnect(dssdev);
 
-       omap_dss_put_device(in);
-
        return 0;
 }
 
index 3f6c90db35c4fe16ad4421ba9052e3f69331ab86..b5d8a00df811b6c91f8c9e60b241f7e0ee7a01f7 100644 (file)
@@ -169,16 +169,25 @@ enum jbt_register {
 static int td028ttec1_panel_connect(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
+       struct omap_dss_device *in;
        int r;
 
        if (omapdss_device_is_connected(dssdev))
                return 0;
 
+       in = omapdss_of_find_source_for_first_ep(dssdev->dev->of_node);
+       if (IS_ERR(in)) {
+               dev_err(dssdev->dev, "failed to find video source\n");
+               return PTR_ERR(in);
+       }
+
        r = in->ops.dpi->connect(in, dssdev);
-       if (r)
+       if (r) {
+               omap_dss_put_device(in);
                return r;
+       }
 
+       ddata->in = in;
        return 0;
 }
 
@@ -191,6 +200,9 @@ static void td028ttec1_panel_disconnect(struct omap_dss_device *dssdev)
                return;
 
        in->ops.dpi->disconnect(in, dssdev);
+
+       omap_dss_put_device(in);
+       ddata->in = NULL;
 }
 
 static int td028ttec1_panel_enable(struct omap_dss_device *dssdev)
@@ -362,23 +374,6 @@ static struct omap_dss_driver td028ttec1_ops = {
        .check_timings  = td028ttec1_panel_check_timings,
 };
 
-static int td028ttec1_probe_of(struct spi_device *spi)
-{
-       struct device_node *node = spi->dev.of_node;
-       struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-       struct omap_dss_device *in;
-
-       in = omapdss_of_find_source_for_first_ep(node);
-       if (IS_ERR(in)) {
-               dev_err(&spi->dev, "failed to find video source\n");
-               return PTR_ERR(in);
-       }
-
-       ddata->in = in;
-
-       return 0;
-}
-
 static int td028ttec1_panel_probe(struct spi_device *spi)
 {
        struct panel_drv_data *ddata;
@@ -404,10 +399,6 @@ static int td028ttec1_panel_probe(struct spi_device *spi)
 
        ddata->spi_dev = spi;
 
-       r = td028ttec1_probe_of(spi);
-       if (r)
-               return r;
-
        ddata->vm = td028ttec1_panel_vm;
 
        dssdev = &ddata->dssdev;
@@ -420,21 +411,16 @@ static int td028ttec1_panel_probe(struct spi_device *spi)
        r = omapdss_register_display(dssdev);
        if (r) {
                dev_err(&spi->dev, "Failed to register panel\n");
-               goto err_reg;
+               return r;
        }
 
        return 0;
-
-err_reg:
-       omap_dss_put_device(ddata->in);
-       return r;
 }
 
 static int td028ttec1_panel_remove(struct spi_device *spi)
 {
        struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
        struct omap_dss_device *dssdev = &ddata->dssdev;
-       struct omap_dss_device *in = ddata->in;
 
        dev_dbg(&ddata->spi_dev->dev, "%s\n", __func__);
 
@@ -443,8 +429,6 @@ static int td028ttec1_panel_remove(struct spi_device *spi)
        td028ttec1_panel_disable(dssdev);
        td028ttec1_panel_disconnect(dssdev);
 
-       omap_dss_put_device(in);
-
        return 0;
 }
 
index 06fb5a9950023bf11affa57bcd628d04fe48b75a..c08e22b434472d99ea1274c38109b6c2d9612909 100644 (file)
@@ -340,16 +340,25 @@ static void tpo_td043_power_off(struct panel_drv_data *ddata)
 static int tpo_td043_connect(struct omap_dss_device *dssdev)
 {
        struct panel_drv_data *ddata = to_panel_data(dssdev);
-       struct omap_dss_device *in = ddata->in;
+       struct omap_dss_device *in;
        int r;
 
        if (omapdss_device_is_connected(dssdev))
                return 0;
 
+       in = omapdss_of_find_source_for_first_ep(dssdev->dev->of_node);
+       if (IS_ERR(in)) {
+               dev_err(dssdev->dev, "failed to find video source\n");
+               return PTR_ERR(in);
+       }
+
        r = in->ops.dpi->connect(in, dssdev);
-       if (r)
+       if (r) {
+               omap_dss_put_device(in);
                return r;
+       }
 
+       ddata->in = in;
        return 0;
 }
 
@@ -362,6 +371,9 @@ static void tpo_td043_disconnect(struct omap_dss_device *dssdev)
                return;
 
        in->ops.dpi->disconnect(in, dssdev);
+
+       omap_dss_put_device(in);
+       ddata->in = NULL;
 }
 
 static int tpo_td043_enable(struct omap_dss_device *dssdev)
@@ -463,7 +475,6 @@ static int tpo_td043_probe_of(struct spi_device *spi)
 {
        struct device_node *node = spi->dev.of_node;
        struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
-       struct omap_dss_device *in;
        int gpio;
 
        gpio = of_get_named_gpio(node, "reset-gpios", 0);
@@ -473,14 +484,6 @@ static int tpo_td043_probe_of(struct spi_device *spi)
        }
        ddata->nreset_gpio = gpio;
 
-       in = omapdss_of_find_source_for_first_ep(node);
-       if (IS_ERR(in)) {
-               dev_err(&spi->dev, "failed to find video source\n");
-               return PTR_ERR(in);
-       }
-
-       ddata->in = in;
-
        return 0;
 }
 
@@ -561,7 +564,6 @@ err_reg:
 err_sysfs:
 err_gpio_req:
 err_regulator:
-       omap_dss_put_device(ddata->in);
        return r;
 }
 
@@ -569,7 +571,6 @@ static int tpo_td043_remove(struct spi_device *spi)
 {
        struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
        struct omap_dss_device *dssdev = &ddata->dssdev;
-       struct omap_dss_device *in = ddata->in;
 
        dev_dbg(&ddata->spi->dev, "%s\n", __func__);
 
@@ -578,8 +579,6 @@ static int tpo_td043_remove(struct spi_device *spi)
        tpo_td043_disable(dssdev);
        tpo_td043_disconnect(dssdev);
 
-       omap_dss_put_device(in);
-
        sysfs_remove_group(&spi->dev.kobj, &tpo_td043_attr_group);
 
        return 0;