aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tilcdc/tilcdc_panel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/tilcdc/tilcdc_panel.c')
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_panel.c74
1 files changed, 57 insertions, 17 deletions
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
index 4c7aa1d8134f..7a0315855e90 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
@@ -18,6 +18,7 @@
18#include <linux/pinctrl/pinmux.h> 18#include <linux/pinctrl/pinmux.h>
19#include <linux/pinctrl/consumer.h> 19#include <linux/pinctrl/consumer.h>
20#include <linux/backlight.h> 20#include <linux/backlight.h>
21#include <linux/gpio/consumer.h>
21#include <video/display_timing.h> 22#include <video/display_timing.h>
22#include <video/of_display_timing.h> 23#include <video/of_display_timing.h>
23#include <video/videomode.h> 24#include <video/videomode.h>
@@ -29,6 +30,7 @@ struct panel_module {
29 struct tilcdc_panel_info *info; 30 struct tilcdc_panel_info *info;
30 struct display_timings *timings; 31 struct display_timings *timings;
31 struct backlight_device *backlight; 32 struct backlight_device *backlight;
33 struct gpio_desc *enable_gpio;
32}; 34};
33#define to_panel_module(x) container_of(x, struct panel_module, base) 35#define to_panel_module(x) container_of(x, struct panel_module, base)
34 36
@@ -55,13 +57,17 @@ static void panel_encoder_dpms(struct drm_encoder *encoder, int mode)
55{ 57{
56 struct panel_encoder *panel_encoder = to_panel_encoder(encoder); 58 struct panel_encoder *panel_encoder = to_panel_encoder(encoder);
57 struct backlight_device *backlight = panel_encoder->mod->backlight; 59 struct backlight_device *backlight = panel_encoder->mod->backlight;
60 struct gpio_desc *gpio = panel_encoder->mod->enable_gpio;
58 61
59 if (!backlight) 62 if (backlight) {
60 return; 63 backlight->props.power = mode == DRM_MODE_DPMS_ON ?
64 FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
65 backlight_update_status(backlight);
66 }
61 67
62 backlight->props.power = mode == DRM_MODE_DPMS_ON 68 if (gpio)
63 ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; 69 gpiod_set_value_cansleep(gpio,
64 backlight_update_status(backlight); 70 mode == DRM_MODE_DPMS_ON ? 1 : 0);
65} 71}
66 72
67static bool panel_encoder_mode_fixup(struct drm_encoder *encoder, 73static bool panel_encoder_mode_fixup(struct drm_encoder *encoder,
@@ -311,6 +317,7 @@ static struct tilcdc_panel_info *of_get_panel_info(struct device_node *np)
311 info = kzalloc(sizeof(*info), GFP_KERNEL); 317 info = kzalloc(sizeof(*info), GFP_KERNEL);
312 if (!info) { 318 if (!info) {
313 pr_err("%s: allocation failed\n", __func__); 319 pr_err("%s: allocation failed\n", __func__);
320 of_node_put(info_np);
314 return NULL; 321 return NULL;
315 } 322 }
316 323
@@ -331,22 +338,21 @@ static struct tilcdc_panel_info *of_get_panel_info(struct device_node *np)
331 if (ret) { 338 if (ret) {
332 pr_err("%s: error reading panel-info properties\n", __func__); 339 pr_err("%s: error reading panel-info properties\n", __func__);
333 kfree(info); 340 kfree(info);
341 of_node_put(info_np);
334 return NULL; 342 return NULL;
335 } 343 }
344 of_node_put(info_np);
336 345
337 return info; 346 return info;
338} 347}
339 348
340static struct of_device_id panel_of_match[];
341
342static int panel_probe(struct platform_device *pdev) 349static int panel_probe(struct platform_device *pdev)
343{ 350{
344 struct device_node *node = pdev->dev.of_node; 351 struct device_node *bl_node, *node = pdev->dev.of_node;
345 struct panel_module *panel_mod; 352 struct panel_module *panel_mod;
346 struct tilcdc_module *mod; 353 struct tilcdc_module *mod;
347 struct pinctrl *pinctrl; 354 struct pinctrl *pinctrl;
348 int ret = -EINVAL; 355 int ret;
349
350 356
351 /* bail out early if no DT data: */ 357 /* bail out early if no DT data: */
352 if (!node) { 358 if (!node) {
@@ -354,10 +360,40 @@ static int panel_probe(struct platform_device *pdev)
354 return -ENXIO; 360 return -ENXIO;
355 } 361 }
356 362
357 panel_mod = kzalloc(sizeof(*panel_mod), GFP_KERNEL); 363 panel_mod = devm_kzalloc(&pdev->dev, sizeof(*panel_mod), GFP_KERNEL);
358 if (!panel_mod) 364 if (!panel_mod)
359 return -ENOMEM; 365 return -ENOMEM;
360 366
367 bl_node = of_parse_phandle(node, "backlight", 0);
368 if (bl_node) {
369 panel_mod->backlight = of_find_backlight_by_node(bl_node);
370 of_node_put(bl_node);
371
372 if (!panel_mod->backlight)
373 return -EPROBE_DEFER;
374
375 dev_info(&pdev->dev, "found backlight\n");
376 }
377
378 panel_mod->enable_gpio = devm_gpiod_get(&pdev->dev, "enable");
379 if (IS_ERR(panel_mod->enable_gpio)) {
380 ret = PTR_ERR(panel_mod->enable_gpio);
381 if (ret != -ENOENT) {
382 dev_err(&pdev->dev, "failed to request enable GPIO\n");
383 goto fail_backlight;
384 }
385
386 /* Optional GPIO is not here, continue silently. */
387 panel_mod->enable_gpio = NULL;
388 } else {
389 ret = gpiod_direction_output(panel_mod->enable_gpio, 0);
390 if (ret < 0) {
391 dev_err(&pdev->dev, "failed to setup GPIO\n");
392 goto fail_backlight;
393 }
394 dev_info(&pdev->dev, "found enable GPIO\n");
395 }
396
361 mod = &panel_mod->base; 397 mod = &panel_mod->base;
362 pdev->dev.platform_data = mod; 398 pdev->dev.platform_data = mod;
363 399
@@ -370,29 +406,30 @@ static int panel_probe(struct platform_device *pdev)
370 panel_mod->timings = of_get_display_timings(node); 406 panel_mod->timings = of_get_display_timings(node);
371 if (!panel_mod->timings) { 407 if (!panel_mod->timings) {
372 dev_err(&pdev->dev, "could not get panel timings\n"); 408 dev_err(&pdev->dev, "could not get panel timings\n");
409 ret = -EINVAL;
373 goto fail_free; 410 goto fail_free;
374 } 411 }
375 412
376 panel_mod->info = of_get_panel_info(node); 413 panel_mod->info = of_get_panel_info(node);
377 if (!panel_mod->info) { 414 if (!panel_mod->info) {
378 dev_err(&pdev->dev, "could not get panel info\n"); 415 dev_err(&pdev->dev, "could not get panel info\n");
416 ret = -EINVAL;
379 goto fail_timings; 417 goto fail_timings;
380 } 418 }
381 419
382 mod->preferred_bpp = panel_mod->info->bpp; 420 mod->preferred_bpp = panel_mod->info->bpp;
383 421
384 panel_mod->backlight = of_find_backlight_by_node(node);
385 if (panel_mod->backlight)
386 dev_info(&pdev->dev, "found backlight\n");
387
388 return 0; 422 return 0;
389 423
390fail_timings: 424fail_timings:
391 display_timings_release(panel_mod->timings); 425 display_timings_release(panel_mod->timings);
392 426
393fail_free: 427fail_free:
394 kfree(panel_mod);
395 tilcdc_module_cleanup(mod); 428 tilcdc_module_cleanup(mod);
429
430fail_backlight:
431 if (panel_mod->backlight)
432 put_device(&panel_mod->backlight->dev);
396 return ret; 433 return ret;
397} 434}
398 435
@@ -400,12 +437,15 @@ static int panel_remove(struct platform_device *pdev)
400{ 437{
401 struct tilcdc_module *mod = dev_get_platdata(&pdev->dev); 438 struct tilcdc_module *mod = dev_get_platdata(&pdev->dev);
402 struct panel_module *panel_mod = to_panel_module(mod); 439 struct panel_module *panel_mod = to_panel_module(mod);
440 struct backlight_device *backlight = panel_mod->backlight;
441
442 if (backlight)
443 put_device(&backlight->dev);
403 444
404 display_timings_release(panel_mod->timings); 445 display_timings_release(panel_mod->timings);
405 446
406 tilcdc_module_cleanup(mod); 447 tilcdc_module_cleanup(mod);
407 kfree(panel_mod->info); 448 kfree(panel_mod->info);
408 kfree(panel_mod);
409 449
410 return 0; 450 return 0;
411} 451}