1*3bf42006SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2ec072b0fSAndrzej Zaborowski /* 3ec072b0fSAndrzej Zaborowski * Backlight driver for OMAP based boards. 4ec072b0fSAndrzej Zaborowski * 5ec072b0fSAndrzej Zaborowski * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org> 6ec072b0fSAndrzej Zaborowski */ 7ec072b0fSAndrzej Zaborowski 8ec072b0fSAndrzej Zaborowski #include <linux/module.h> 9ec072b0fSAndrzej Zaborowski #include <linux/kernel.h> 10ec072b0fSAndrzej Zaborowski #include <linux/init.h> 11ec072b0fSAndrzej Zaborowski #include <linux/platform_device.h> 12ec072b0fSAndrzej Zaborowski #include <linux/fb.h> 13ec072b0fSAndrzej Zaborowski #include <linux/backlight.h> 145a0e3ad6STejun Heo #include <linux/slab.h> 15cc012729SIgor Grinberg #include <linux/platform_data/omap1_bl.h> 16ec072b0fSAndrzej Zaborowski 17a09e64fbSRussell King #include <mach/hardware.h> 1870c494c3STony Lindgren #include <mach/mux.h> 19ec072b0fSAndrzej Zaborowski 20ec072b0fSAndrzej Zaborowski #define OMAPBL_MAX_INTENSITY 0xff 21ec072b0fSAndrzej Zaborowski 22ec072b0fSAndrzej Zaborowski struct omap_backlight { 23ec072b0fSAndrzej Zaborowski int powermode; 24ec072b0fSAndrzej Zaborowski int current_intensity; 25ec072b0fSAndrzej Zaborowski 26ec072b0fSAndrzej Zaborowski struct device *dev; 27ec072b0fSAndrzej Zaborowski struct omap_backlight_config *pdata; 28ec072b0fSAndrzej Zaborowski }; 29ec072b0fSAndrzej Zaborowski 307a94f653SJingoo Han static inline void omapbl_send_intensity(int intensity) 31ec072b0fSAndrzej Zaborowski { 32ec072b0fSAndrzej Zaborowski omap_writeb(intensity, OMAP_PWL_ENABLE); 33ec072b0fSAndrzej Zaborowski } 34ec072b0fSAndrzej Zaborowski 357a94f653SJingoo Han static inline void omapbl_send_enable(int enable) 36ec072b0fSAndrzej Zaborowski { 37ec072b0fSAndrzej Zaborowski omap_writeb(enable, OMAP_PWL_CLK_ENABLE); 38ec072b0fSAndrzej Zaborowski } 39ec072b0fSAndrzej Zaborowski 40ec072b0fSAndrzej Zaborowski static void omapbl_blank(struct omap_backlight *bl, int mode) 41ec072b0fSAndrzej Zaborowski { 42ec072b0fSAndrzej Zaborowski if (bl->pdata->set_power) 43ec072b0fSAndrzej Zaborowski bl->pdata->set_power(bl->dev, mode); 44ec072b0fSAndrzej Zaborowski 45ec072b0fSAndrzej Zaborowski switch (mode) { 46ec072b0fSAndrzej Zaborowski case FB_BLANK_NORMAL: 47ec072b0fSAndrzej Zaborowski case FB_BLANK_VSYNC_SUSPEND: 48ec072b0fSAndrzej Zaborowski case FB_BLANK_HSYNC_SUSPEND: 49ec072b0fSAndrzej Zaborowski case FB_BLANK_POWERDOWN: 50ec072b0fSAndrzej Zaborowski omapbl_send_intensity(0); 51ec072b0fSAndrzej Zaborowski omapbl_send_enable(0); 52ec072b0fSAndrzej Zaborowski break; 53ec072b0fSAndrzej Zaborowski 54ec072b0fSAndrzej Zaborowski case FB_BLANK_UNBLANK: 55ec072b0fSAndrzej Zaborowski omapbl_send_intensity(bl->current_intensity); 56ec072b0fSAndrzej Zaborowski omapbl_send_enable(1); 57ec072b0fSAndrzej Zaborowski break; 58ec072b0fSAndrzej Zaborowski } 59ec072b0fSAndrzej Zaborowski } 60ec072b0fSAndrzej Zaborowski 6107cac9d7SJingoo Han #ifdef CONFIG_PM_SLEEP 6207cac9d7SJingoo Han static int omapbl_suspend(struct device *dev) 63ec072b0fSAndrzej Zaborowski { 6407cac9d7SJingoo Han struct backlight_device *bl_dev = dev_get_drvdata(dev); 6507cac9d7SJingoo Han struct omap_backlight *bl = bl_get_data(bl_dev); 66ec072b0fSAndrzej Zaborowski 67ec072b0fSAndrzej Zaborowski omapbl_blank(bl, FB_BLANK_POWERDOWN); 68ec072b0fSAndrzej Zaborowski return 0; 69ec072b0fSAndrzej Zaborowski } 70ec072b0fSAndrzej Zaborowski 7107cac9d7SJingoo Han static int omapbl_resume(struct device *dev) 72ec072b0fSAndrzej Zaborowski { 7307cac9d7SJingoo Han struct backlight_device *bl_dev = dev_get_drvdata(dev); 7407cac9d7SJingoo Han struct omap_backlight *bl = bl_get_data(bl_dev); 75ec072b0fSAndrzej Zaborowski 76ec072b0fSAndrzej Zaborowski omapbl_blank(bl, bl->powermode); 77ec072b0fSAndrzej Zaborowski return 0; 78ec072b0fSAndrzej Zaborowski } 79ec072b0fSAndrzej Zaborowski #endif 80ec072b0fSAndrzej Zaborowski 81ec072b0fSAndrzej Zaborowski static int omapbl_set_power(struct backlight_device *dev, int state) 82ec072b0fSAndrzej Zaborowski { 835f42d5b2SJingoo Han struct omap_backlight *bl = bl_get_data(dev); 84ec072b0fSAndrzej Zaborowski 85ec072b0fSAndrzej Zaborowski omapbl_blank(bl, state); 86ec072b0fSAndrzej Zaborowski bl->powermode = state; 87ec072b0fSAndrzej Zaborowski 88ec072b0fSAndrzej Zaborowski return 0; 89ec072b0fSAndrzej Zaborowski } 90ec072b0fSAndrzej Zaborowski 91ec072b0fSAndrzej Zaborowski static int omapbl_update_status(struct backlight_device *dev) 92ec072b0fSAndrzej Zaborowski { 935f42d5b2SJingoo Han struct omap_backlight *bl = bl_get_data(dev); 94ec072b0fSAndrzej Zaborowski 95ec072b0fSAndrzej Zaborowski if (bl->current_intensity != dev->props.brightness) { 96ec072b0fSAndrzej Zaborowski if (bl->powermode == FB_BLANK_UNBLANK) 97ec072b0fSAndrzej Zaborowski omapbl_send_intensity(dev->props.brightness); 98ec072b0fSAndrzej Zaborowski bl->current_intensity = dev->props.brightness; 99ec072b0fSAndrzej Zaborowski } 100ec072b0fSAndrzej Zaborowski 101ec072b0fSAndrzej Zaborowski if (dev->props.fb_blank != bl->powermode) 102ec072b0fSAndrzej Zaborowski omapbl_set_power(dev, dev->props.fb_blank); 103ec072b0fSAndrzej Zaborowski 104ec072b0fSAndrzej Zaborowski return 0; 105ec072b0fSAndrzej Zaborowski } 106ec072b0fSAndrzej Zaborowski 107ec072b0fSAndrzej Zaborowski static int omapbl_get_intensity(struct backlight_device *dev) 108ec072b0fSAndrzej Zaborowski { 1095f42d5b2SJingoo Han struct omap_backlight *bl = bl_get_data(dev); 110b6af73b4SJingoo Han 111ec072b0fSAndrzej Zaborowski return bl->current_intensity; 112ec072b0fSAndrzej Zaborowski } 113ec072b0fSAndrzej Zaborowski 1149905a43bSEmese Revfy static const struct backlight_ops omapbl_ops = { 115ec072b0fSAndrzej Zaborowski .get_brightness = omapbl_get_intensity, 116ec072b0fSAndrzej Zaborowski .update_status = omapbl_update_status, 117ec072b0fSAndrzej Zaborowski }; 118ec072b0fSAndrzej Zaborowski 119ec072b0fSAndrzej Zaborowski static int omapbl_probe(struct platform_device *pdev) 120ec072b0fSAndrzej Zaborowski { 121a19a6ee6SMatthew Garrett struct backlight_properties props; 122ec072b0fSAndrzej Zaborowski struct backlight_device *dev; 123ec072b0fSAndrzej Zaborowski struct omap_backlight *bl; 124c512794cSJingoo Han struct omap_backlight_config *pdata = dev_get_platdata(&pdev->dev); 125ec072b0fSAndrzej Zaborowski 126ec072b0fSAndrzej Zaborowski if (!pdata) 127ec072b0fSAndrzej Zaborowski return -ENXIO; 128ec072b0fSAndrzej Zaborowski 129ce969228SJulia Lawall bl = devm_kzalloc(&pdev->dev, sizeof(struct omap_backlight), 130ce969228SJulia Lawall GFP_KERNEL); 131ec072b0fSAndrzej Zaborowski if (unlikely(!bl)) 132ec072b0fSAndrzej Zaborowski return -ENOMEM; 133ec072b0fSAndrzej Zaborowski 134a19a6ee6SMatthew Garrett memset(&props, 0, sizeof(struct backlight_properties)); 135bb7ca747SMatthew Garrett props.type = BACKLIGHT_RAW; 136a19a6ee6SMatthew Garrett props.max_brightness = OMAPBL_MAX_INTENSITY; 137c76d1022SJingoo Han dev = devm_backlight_device_register(&pdev->dev, "omap-bl", &pdev->dev, 138c76d1022SJingoo Han bl, &omapbl_ops, &props); 139ce969228SJulia Lawall if (IS_ERR(dev)) 140ec072b0fSAndrzej Zaborowski return PTR_ERR(dev); 141ec072b0fSAndrzej Zaborowski 142ec072b0fSAndrzej Zaborowski bl->powermode = FB_BLANK_POWERDOWN; 143ec072b0fSAndrzej Zaborowski bl->current_intensity = 0; 144ec072b0fSAndrzej Zaborowski 145ec072b0fSAndrzej Zaborowski bl->pdata = pdata; 146ec072b0fSAndrzej Zaborowski bl->dev = &pdev->dev; 147ec072b0fSAndrzej Zaborowski 148ec072b0fSAndrzej Zaborowski platform_set_drvdata(pdev, dev); 149ec072b0fSAndrzej Zaborowski 150ec072b0fSAndrzej Zaborowski omap_cfg_reg(PWL); /* Conflicts with UART3 */ 151ec072b0fSAndrzej Zaborowski 152ec072b0fSAndrzej Zaborowski dev->props.fb_blank = FB_BLANK_UNBLANK; 153ec072b0fSAndrzej Zaborowski dev->props.brightness = pdata->default_intensity; 154ec072b0fSAndrzej Zaborowski omapbl_update_status(dev); 155ec072b0fSAndrzej Zaborowski 1568e1274a3SJingoo Han dev_info(&pdev->dev, "OMAP LCD backlight initialised\n"); 157ec072b0fSAndrzej Zaborowski 158ec072b0fSAndrzej Zaborowski return 0; 159ec072b0fSAndrzej Zaborowski } 160ec072b0fSAndrzej Zaborowski 16107cac9d7SJingoo Han static SIMPLE_DEV_PM_OPS(omapbl_pm_ops, omapbl_suspend, omapbl_resume); 16207cac9d7SJingoo Han 163ec072b0fSAndrzej Zaborowski static struct platform_driver omapbl_driver = { 164ec072b0fSAndrzej Zaborowski .probe = omapbl_probe, 165ec072b0fSAndrzej Zaborowski .driver = { 166ec072b0fSAndrzej Zaborowski .name = "omap-bl", 16707cac9d7SJingoo Han .pm = &omapbl_pm_ops, 168ec072b0fSAndrzej Zaborowski }, 169ec072b0fSAndrzej Zaborowski }; 170ec072b0fSAndrzej Zaborowski 17181178e02SAxel Lin module_platform_driver(omapbl_driver); 172ec072b0fSAndrzej Zaborowski 173ec072b0fSAndrzej Zaborowski MODULE_AUTHOR("Andrzej Zaborowski <balrog@zabor.org>"); 174ec072b0fSAndrzej Zaborowski MODULE_DESCRIPTION("OMAP LCD Backlight driver"); 175ec072b0fSAndrzej Zaborowski MODULE_LICENSE("GPL"); 176