diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 91 |
1 files changed, 60 insertions, 31 deletions
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c index 84591396451c..d139bb70a5e7 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c @@ -51,6 +51,7 @@ struct panel_drv_data { 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 @@ -100,6 +101,30 @@ static int dsicm_panel_reset(struct panel_drv_data *ddata); 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); @@ -343,7 +368,7 @@ static int dsicm_bl_update_status(struct backlight_device *dev) { 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 && @@ -364,8 +389,6 @@ static int dsicm_bl_update_status(struct backlight_device *dev) r = dsicm_dcs_write_1(ddata, DCS_BRIGHTNESS, level); in->ops.dsi->bus_unlock(in); - } else { - r = 0; } mutex_unlock(&ddata->lock); @@ -819,6 +842,8 @@ static int dsicm_enable(struct omap_dss_device *dssdev) mutex_unlock(&ddata->lock); + dsicm_bl_power(ddata, true); + return 0; err: dev_dbg(&ddata->pdev->dev, "enable failed\n"); @@ -834,6 +859,8 @@ static void dsicm_disable(struct omap_dss_device *dssdev) dev_dbg(&ddata->pdev->dev, "disable\n"); + dsicm_bl_power(ddata, false); + mutex_lock(&ddata->lock); dsicm_cancel_ulps_work(ddata); @@ -1198,6 +1225,7 @@ static struct omap_dss_driver dsicm_ops = { 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; @@ -1259,14 +1287,25 @@ static int dsicm_probe_of(struct platform_device *pdev) 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; @@ -1319,7 +1358,7 @@ static int dsicm_probe(struct platform_device *pdev) GPIOF_OUT_INIT_LOW, "taal rst"); if (r) { dev_err(dev, "failed to request reset gpio\n"); - return r; + goto err_reg; } } @@ -1328,7 +1367,7 @@ static int dsicm_probe(struct platform_device *pdev) 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), @@ -1338,7 +1377,7 @@ static int dsicm_probe(struct platform_device *pdev) if (r) { dev_err(dev, "IRQ request failed\n"); - return r; + goto err_reg; } INIT_DEFERRABLE_WORK(&ddata->te_timeout_work, @@ -1348,48 +1387,43 @@ static int dsicm_probe(struct platform_device *pdev) } 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; } @@ -1397,7 +1431,6 @@ static int __exit dsicm_remove(struct platform_device *pdev) { 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"); @@ -1408,12 +1441,8 @@ static int __exit dsicm_remove(struct platform_device *pdev) 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); |