struct mutex lock;
 
        struct backlight_device *bldev;
+       struct backlight_device *extbldev;
 
        unsigned long   hw_guard_end;   /* next value of jiffies when we can
                                         * issue the next sleep in/out command
 
 static void dsicm_ulps_work(struct work_struct *work);
 
+static void dsicm_bl_power(struct panel_drv_data *ddata, bool enable)
+{
+       struct backlight_device *backlight;
+
+       if (ddata->bldev)
+               backlight = ddata->bldev;
+       else if (ddata->extbldev)
+               backlight = ddata->extbldev;
+       else
+               return;
+
+       if (enable) {
+               backlight->props.fb_blank = FB_BLANK_UNBLANK;
+               backlight->props.state = ~(BL_CORE_FBBLANK | BL_CORE_SUSPENDED);
+               backlight->props.power = FB_BLANK_UNBLANK;
+       } else {
+               backlight->props.fb_blank = FB_BLANK_NORMAL;
+               backlight->props.power = FB_BLANK_POWERDOWN;
+               backlight->props.state |= BL_CORE_FBBLANK | BL_CORE_SUSPENDED;
+       }
+
+       backlight_update_status(backlight);
+}
+
 static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
 {
        ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
 {
        struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
        struct omap_dss_device *in = ddata->in;
-       int r;
+       int r = 0;
        int level;
 
        if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
                        r = dsicm_dcs_write_1(ddata, DCS_BRIGHTNESS, level);
 
                in->ops.dsi->bus_unlock(in);
-       } else {
-               r = 0;
        }
 
        mutex_unlock(&ddata->lock);
 
        mutex_unlock(&ddata->lock);
 
+       dsicm_bl_power(ddata, true);
+
        return 0;
 err:
        dev_dbg(&ddata->pdev->dev, "enable failed\n");
 
        dev_dbg(&ddata->pdev->dev, "disable\n");
 
+       dsicm_bl_power(ddata, false);
+
        mutex_lock(&ddata->lock);
 
        dsicm_cancel_ulps_work(ddata);
 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;
 
        ddata->in = in;
 
-       /* TODO: ulps, backlight */
+       backlight = of_parse_phandle(node, "backlight", 0);
+       if (backlight) {
+               ddata->extbldev = of_find_backlight_by_node(backlight);
+               of_node_put(backlight);
+
+               if (!ddata->extbldev)
+                       return -EPROBE_DEFER;
+       } else {
+               /* assume native backlight support */
+               ddata->use_dsi_backlight = true;
+       }
+
+       /* TODO: ulps */
 
        return 0;
 }
 
 static int dsicm_probe(struct platform_device *pdev)
 {
-       struct backlight_properties props;
        struct panel_drv_data *ddata;
        struct backlight_device *bldev = NULL;
        struct device *dev = &pdev->dev;
                                GPIOF_OUT_INIT_LOW, "taal rst");
                if (r) {
                        dev_err(dev, "failed to request reset gpio\n");
-                       return r;
+                       goto err_reg;
                }
        }
 
                                GPIOF_IN, "taal irq");
                if (r) {
                        dev_err(dev, "GPIO request failed\n");
-                       return r;
+                       goto err_reg;
                }
 
                r = devm_request_irq(dev, gpio_to_irq(ddata->ext_te_gpio),
 
                if (r) {
                        dev_err(dev, "IRQ request failed\n");
-                       return r;
+                       goto err_reg;
                }
 
                INIT_DEFERRABLE_WORK(&ddata->te_timeout_work,
        }
 
        ddata->workqueue = create_singlethread_workqueue("dsicm_wq");
-       if (ddata->workqueue == NULL) {
-               dev_err(dev, "can't create workqueue\n");
-               return -ENOMEM;
+       if (!ddata->workqueue) {
+               r = -ENOMEM;
+               goto err_reg;
        }
        INIT_DELAYED_WORK(&ddata->ulps_work, dsicm_ulps_work);
 
        dsicm_hw_reset(ddata);
 
        if (ddata->use_dsi_backlight) {
-               memset(&props, 0, sizeof(props));
+               struct backlight_properties props = { 0 };
                props.max_brightness = 255;
-
                props.type = BACKLIGHT_RAW;
-               bldev = backlight_device_register(dev_name(dev),
-                               dev, ddata, &dsicm_bl_ops, &props);
+
+               bldev = devm_backlight_device_register(dev, dev_name(dev),
+                       dev, ddata, &dsicm_bl_ops, &props);
                if (IS_ERR(bldev)) {
                        r = PTR_ERR(bldev);
                        goto err_bl;
                }
 
                ddata->bldev = bldev;
-
-               bldev->props.fb_blank = FB_BLANK_UNBLANK;
-               bldev->props.power = FB_BLANK_UNBLANK;
-               bldev->props.brightness = 255;
-
-               dsicm_bl_update_status(bldev);
        }
 
        r = sysfs_create_group(&dev->kobj, &dsicm_attr_group);
        if (r) {
                dev_err(dev, "failed to create sysfs files\n");
-               goto err_sysfs_create;
+               goto err_bl;
        }
 
        return 0;
 
-err_sysfs_create:
-       backlight_device_unregister(bldev);
 err_bl:
        destroy_workqueue(ddata->workqueue);
 err_reg:
+       if (ddata->extbldev)
+               put_device(&ddata->extbldev->dev);
+
        return r;
 }
 
 {
        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
        struct omap_dss_device *dssdev = &ddata->dssdev;
-       struct backlight_device *bldev;
 
        dev_dbg(&pdev->dev, "remove\n");
 
 
        sysfs_remove_group(&pdev->dev.kobj, &dsicm_attr_group);
 
-       bldev = ddata->bldev;
-       if (bldev != NULL) {
-               bldev->props.power = FB_BLANK_POWERDOWN;
-               dsicm_bl_update_status(bldev);
-               backlight_device_unregister(bldev);
-       }
+       if (ddata->extbldev)
+               put_device(&ddata->extbldev->dev);
 
        omap_dss_put_device(ddata->in);