0011-drm-omap-panel-dsi-cm-add-external-backlight-support.patch (6955B)
1 From ed924fc352d6e2caa0d3fc1be1f1c65a35c9343b Mon Sep 17 00:00:00 2001 2 From: Sebastian Reichel <sebastian.reichel@collabora.co.uk> 3 Date: Mon, 24 Jul 2017 19:33:08 +0200 4 Subject: [PATCH 11/17] drm/omap: panel-dsi-cm: add external backlight support 5 6 Droid 4 has a command mode DSI panel, which does not have/use 7 DSI based backlight support. This adds proper support for this 8 using a backlight phandle property, which follows the common 9 panel binding. 10 11 If no backlight phandle is found, it is assumed, that the 12 native backlight should be used instead. This is used by 13 the Nokia N950. 14 15 Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk> 16 --- 17 drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 91 ++++++++++++++++--------- 18 1 file changed, 60 insertions(+), 31 deletions(-) 19 20 diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c 21 index 8459139..d139bb7 100644 22 --- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c 23 +++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c 24 @@ -51,6 +51,7 @@ struct panel_drv_data { 25 struct mutex lock; 26 27 struct backlight_device *bldev; 28 + struct backlight_device *extbldev; 29 30 unsigned long hw_guard_end; /* next value of jiffies when we can 31 * issue the next sleep in/out command 32 @@ -100,6 +101,30 @@ static int dsicm_panel_reset(struct panel_drv_data *ddata); 33 34 static void dsicm_ulps_work(struct work_struct *work); 35 36 +static void dsicm_bl_power(struct panel_drv_data *ddata, bool enable) 37 +{ 38 + struct backlight_device *backlight; 39 + 40 + if (ddata->bldev) 41 + backlight = ddata->bldev; 42 + else if (ddata->extbldev) 43 + backlight = ddata->extbldev; 44 + else 45 + return; 46 + 47 + if (enable) { 48 + backlight->props.fb_blank = FB_BLANK_UNBLANK; 49 + backlight->props.state = ~(BL_CORE_FBBLANK | BL_CORE_SUSPENDED); 50 + backlight->props.power = FB_BLANK_UNBLANK; 51 + } else { 52 + backlight->props.fb_blank = FB_BLANK_NORMAL; 53 + backlight->props.power = FB_BLANK_POWERDOWN; 54 + backlight->props.state |= BL_CORE_FBBLANK | BL_CORE_SUSPENDED; 55 + } 56 + 57 + backlight_update_status(backlight); 58 +} 59 + 60 static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec) 61 { 62 ddata->hw_guard_wait = msecs_to_jiffies(guard_msec); 63 @@ -343,7 +368,7 @@ static int dsicm_bl_update_status(struct backlight_device *dev) 64 { 65 struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev); 66 struct omap_dss_device *in = ddata->in; 67 - int r; 68 + int r = 0; 69 int level; 70 71 if (dev->props.fb_blank == FB_BLANK_UNBLANK && 72 @@ -364,8 +389,6 @@ static int dsicm_bl_update_status(struct backlight_device *dev) 73 r = dsicm_dcs_write_1(ddata, DCS_BRIGHTNESS, level); 74 75 in->ops.dsi->bus_unlock(in); 76 - } else { 77 - r = 0; 78 } 79 80 mutex_unlock(&ddata->lock); 81 @@ -819,6 +842,8 @@ static int dsicm_enable(struct omap_dss_device *dssdev) 82 83 mutex_unlock(&ddata->lock); 84 85 + dsicm_bl_power(ddata, true); 86 + 87 return 0; 88 err: 89 dev_dbg(&ddata->pdev->dev, "enable failed\n"); 90 @@ -834,6 +859,8 @@ static void dsicm_disable(struct omap_dss_device *dssdev) 91 92 dev_dbg(&ddata->pdev->dev, "disable\n"); 93 94 + dsicm_bl_power(ddata, false); 95 + 96 mutex_lock(&ddata->lock); 97 98 dsicm_cancel_ulps_work(ddata); 99 @@ -1198,6 +1225,7 @@ static struct omap_dss_driver dsicm_ops = { 100 static int dsicm_probe_of(struct platform_device *pdev) 101 { 102 struct device_node *node = pdev->dev.of_node; 103 + struct device_node *backlight; 104 struct panel_drv_data *ddata = platform_get_drvdata(pdev); 105 struct omap_dss_device *in; 106 struct display_timing timing; 107 @@ -1259,14 +1287,25 @@ static int dsicm_probe_of(struct platform_device *pdev) 108 109 ddata->in = in; 110 111 - /* TODO: ulps, backlight */ 112 + backlight = of_parse_phandle(node, "backlight", 0); 113 + if (backlight) { 114 + ddata->extbldev = of_find_backlight_by_node(backlight); 115 + of_node_put(backlight); 116 + 117 + if (!ddata->extbldev) 118 + return -EPROBE_DEFER; 119 + } else { 120 + /* assume native backlight support */ 121 + ddata->use_dsi_backlight = true; 122 + } 123 + 124 + /* TODO: ulps */ 125 126 return 0; 127 } 128 129 static int dsicm_probe(struct platform_device *pdev) 130 { 131 - struct backlight_properties props; 132 struct panel_drv_data *ddata; 133 struct backlight_device *bldev = NULL; 134 struct device *dev = &pdev->dev; 135 @@ -1319,7 +1358,7 @@ static int dsicm_probe(struct platform_device *pdev) 136 GPIOF_OUT_INIT_LOW, "taal rst"); 137 if (r) { 138 dev_err(dev, "failed to request reset gpio\n"); 139 - return r; 140 + goto err_reg; 141 } 142 } 143 144 @@ -1328,7 +1367,7 @@ static int dsicm_probe(struct platform_device *pdev) 145 GPIOF_IN, "taal irq"); 146 if (r) { 147 dev_err(dev, "GPIO request failed\n"); 148 - return r; 149 + goto err_reg; 150 } 151 152 r = devm_request_irq(dev, gpio_to_irq(ddata->ext_te_gpio), 153 @@ -1338,7 +1377,7 @@ static int dsicm_probe(struct platform_device *pdev) 154 155 if (r) { 156 dev_err(dev, "IRQ request failed\n"); 157 - return r; 158 + goto err_reg; 159 } 160 161 INIT_DEFERRABLE_WORK(&ddata->te_timeout_work, 162 @@ -1348,48 +1387,43 @@ static int dsicm_probe(struct platform_device *pdev) 163 } 164 165 ddata->workqueue = create_singlethread_workqueue("dsicm_wq"); 166 - if (ddata->workqueue == NULL) { 167 - dev_err(dev, "can't create workqueue\n"); 168 - return -ENOMEM; 169 + if (!ddata->workqueue) { 170 + r = -ENOMEM; 171 + goto err_reg; 172 } 173 INIT_DELAYED_WORK(&ddata->ulps_work, dsicm_ulps_work); 174 175 dsicm_hw_reset(ddata); 176 177 if (ddata->use_dsi_backlight) { 178 - memset(&props, 0, sizeof(props)); 179 + struct backlight_properties props = { 0 }; 180 props.max_brightness = 255; 181 - 182 props.type = BACKLIGHT_RAW; 183 - bldev = backlight_device_register(dev_name(dev), 184 - dev, ddata, &dsicm_bl_ops, &props); 185 + 186 + bldev = devm_backlight_device_register(dev, dev_name(dev), 187 + dev, ddata, &dsicm_bl_ops, &props); 188 if (IS_ERR(bldev)) { 189 r = PTR_ERR(bldev); 190 goto err_bl; 191 } 192 193 ddata->bldev = bldev; 194 - 195 - bldev->props.fb_blank = FB_BLANK_UNBLANK; 196 - bldev->props.power = FB_BLANK_UNBLANK; 197 - bldev->props.brightness = 255; 198 - 199 - dsicm_bl_update_status(bldev); 200 } 201 202 r = sysfs_create_group(&dev->kobj, &dsicm_attr_group); 203 if (r) { 204 dev_err(dev, "failed to create sysfs files\n"); 205 - goto err_sysfs_create; 206 + goto err_bl; 207 } 208 209 return 0; 210 211 -err_sysfs_create: 212 - backlight_device_unregister(bldev); 213 err_bl: 214 destroy_workqueue(ddata->workqueue); 215 err_reg: 216 + if (ddata->extbldev) 217 + put_device(&ddata->extbldev->dev); 218 + 219 return r; 220 } 221 222 @@ -1397,7 +1431,6 @@ static int __exit dsicm_remove(struct platform_device *pdev) 223 { 224 struct panel_drv_data *ddata = platform_get_drvdata(pdev); 225 struct omap_dss_device *dssdev = &ddata->dssdev; 226 - struct backlight_device *bldev; 227 228 dev_dbg(&pdev->dev, "remove\n"); 229 230 @@ -1408,12 +1441,8 @@ static int __exit dsicm_remove(struct platform_device *pdev) 231 232 sysfs_remove_group(&pdev->dev.kobj, &dsicm_attr_group); 233 234 - bldev = ddata->bldev; 235 - if (bldev != NULL) { 236 - bldev->props.power = FB_BLANK_POWERDOWN; 237 - dsicm_bl_update_status(bldev); 238 - backlight_device_unregister(bldev); 239 - } 240 + if (ddata->extbldev) 241 + put_device(&ddata->extbldev->dev); 242 243 omap_dss_put_device(ddata->in); 244 245 -- 246 2.1.4 247