162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Backlight driver for OMAP based boards. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/module.h> 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/init.h> 1162306a36Sopenharmony_ci#include <linux/platform_device.h> 1262306a36Sopenharmony_ci#include <linux/fb.h> 1362306a36Sopenharmony_ci#include <linux/backlight.h> 1462306a36Sopenharmony_ci#include <linux/slab.h> 1562306a36Sopenharmony_ci#include <linux/platform_data/omap1_bl.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <linux/soc/ti/omap1-io.h> 1862306a36Sopenharmony_ci#include <linux/soc/ti/omap1-mux.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define OMAPBL_MAX_INTENSITY 0xff 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistruct omap_backlight { 2362306a36Sopenharmony_ci int powermode; 2462306a36Sopenharmony_ci int current_intensity; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci struct device *dev; 2762306a36Sopenharmony_ci struct omap_backlight_config *pdata; 2862306a36Sopenharmony_ci}; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic inline void omapbl_send_intensity(int intensity) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci omap_writeb(intensity, OMAP_PWL_ENABLE); 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic inline void omapbl_send_enable(int enable) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci omap_writeb(enable, OMAP_PWL_CLK_ENABLE); 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic void omapbl_blank(struct omap_backlight *bl, int mode) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci if (bl->pdata->set_power) 4362306a36Sopenharmony_ci bl->pdata->set_power(bl->dev, mode); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci switch (mode) { 4662306a36Sopenharmony_ci case FB_BLANK_NORMAL: 4762306a36Sopenharmony_ci case FB_BLANK_VSYNC_SUSPEND: 4862306a36Sopenharmony_ci case FB_BLANK_HSYNC_SUSPEND: 4962306a36Sopenharmony_ci case FB_BLANK_POWERDOWN: 5062306a36Sopenharmony_ci omapbl_send_intensity(0); 5162306a36Sopenharmony_ci omapbl_send_enable(0); 5262306a36Sopenharmony_ci break; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci case FB_BLANK_UNBLANK: 5562306a36Sopenharmony_ci omapbl_send_intensity(bl->current_intensity); 5662306a36Sopenharmony_ci omapbl_send_enable(1); 5762306a36Sopenharmony_ci break; 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 6262306a36Sopenharmony_cistatic int omapbl_suspend(struct device *dev) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci struct backlight_device *bl_dev = dev_get_drvdata(dev); 6562306a36Sopenharmony_ci struct omap_backlight *bl = bl_get_data(bl_dev); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci omapbl_blank(bl, FB_BLANK_POWERDOWN); 6862306a36Sopenharmony_ci return 0; 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic int omapbl_resume(struct device *dev) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci struct backlight_device *bl_dev = dev_get_drvdata(dev); 7462306a36Sopenharmony_ci struct omap_backlight *bl = bl_get_data(bl_dev); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci omapbl_blank(bl, bl->powermode); 7762306a36Sopenharmony_ci return 0; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci#endif 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic int omapbl_set_power(struct backlight_device *dev, int state) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci struct omap_backlight *bl = bl_get_data(dev); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci omapbl_blank(bl, state); 8662306a36Sopenharmony_ci bl->powermode = state; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci return 0; 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic int omapbl_update_status(struct backlight_device *dev) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci struct omap_backlight *bl = bl_get_data(dev); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci if (bl->current_intensity != dev->props.brightness) { 9662306a36Sopenharmony_ci if (bl->powermode == FB_BLANK_UNBLANK) 9762306a36Sopenharmony_ci omapbl_send_intensity(dev->props.brightness); 9862306a36Sopenharmony_ci bl->current_intensity = dev->props.brightness; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci if (dev->props.fb_blank != bl->powermode) 10262306a36Sopenharmony_ci omapbl_set_power(dev, dev->props.fb_blank); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci return 0; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic int omapbl_get_intensity(struct backlight_device *dev) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci struct omap_backlight *bl = bl_get_data(dev); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci return bl->current_intensity; 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic const struct backlight_ops omapbl_ops = { 11562306a36Sopenharmony_ci .get_brightness = omapbl_get_intensity, 11662306a36Sopenharmony_ci .update_status = omapbl_update_status, 11762306a36Sopenharmony_ci}; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic int omapbl_probe(struct platform_device *pdev) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci struct backlight_properties props; 12262306a36Sopenharmony_ci struct backlight_device *dev; 12362306a36Sopenharmony_ci struct omap_backlight *bl; 12462306a36Sopenharmony_ci struct omap_backlight_config *pdata = dev_get_platdata(&pdev->dev); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci if (!pdata) 12762306a36Sopenharmony_ci return -ENXIO; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci bl = devm_kzalloc(&pdev->dev, sizeof(struct omap_backlight), 13062306a36Sopenharmony_ci GFP_KERNEL); 13162306a36Sopenharmony_ci if (unlikely(!bl)) 13262306a36Sopenharmony_ci return -ENOMEM; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci memset(&props, 0, sizeof(struct backlight_properties)); 13562306a36Sopenharmony_ci props.type = BACKLIGHT_RAW; 13662306a36Sopenharmony_ci props.max_brightness = OMAPBL_MAX_INTENSITY; 13762306a36Sopenharmony_ci dev = devm_backlight_device_register(&pdev->dev, "omap-bl", &pdev->dev, 13862306a36Sopenharmony_ci bl, &omapbl_ops, &props); 13962306a36Sopenharmony_ci if (IS_ERR(dev)) 14062306a36Sopenharmony_ci return PTR_ERR(dev); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci bl->powermode = FB_BLANK_POWERDOWN; 14362306a36Sopenharmony_ci bl->current_intensity = 0; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci bl->pdata = pdata; 14662306a36Sopenharmony_ci bl->dev = &pdev->dev; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci platform_set_drvdata(pdev, dev); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci omap_cfg_reg(PWL); /* Conflicts with UART3 */ 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci dev->props.fb_blank = FB_BLANK_UNBLANK; 15362306a36Sopenharmony_ci dev->props.brightness = pdata->default_intensity; 15462306a36Sopenharmony_ci omapbl_update_status(dev); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci dev_info(&pdev->dev, "OMAP LCD backlight initialised\n"); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci return 0; 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(omapbl_pm_ops, omapbl_suspend, omapbl_resume); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic struct platform_driver omapbl_driver = { 16462306a36Sopenharmony_ci .probe = omapbl_probe, 16562306a36Sopenharmony_ci .driver = { 16662306a36Sopenharmony_ci .name = "omap-bl", 16762306a36Sopenharmony_ci .pm = &omapbl_pm_ops, 16862306a36Sopenharmony_ci }, 16962306a36Sopenharmony_ci}; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cimodule_platform_driver(omapbl_driver); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ciMODULE_AUTHOR("Andrzej Zaborowski <balrog@zabor.org>"); 17462306a36Sopenharmony_ciMODULE_DESCRIPTION("OMAP LCD Backlight driver"); 17562306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 176