1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (c) 2022 Svyatoslav Ryhel <clamor95@gmail.com> 4 */ 5 6#define LOG_CATEGORY UCLASS_PANEL_BACKLIGHT 7 8#include <backlight.h> 9#include <dm.h> 10#include <i2c.h> 11#include <log.h> 12#include <linux/delay.h> 13#include <linux/err.h> 14#include <asm/gpio.h> 15 16#define LM3533_BL_MIN_BRIGHTNESS 0x02 17#define LM3533_BL_MAX_BRIGHTNESS 0xFF 18 19#define LM3533_SINK_OUTPUT_CONFIG_1 0x10 20#define LM3533_CONTROL_BANK_A_PWM 0x14 21#define LM3533_CONTROL_BANK_AB_BRIGHTNESS 0x1A 22#define LM3533_CONTROL_BANK_A_FULLSCALE_CURRENT 0x1F 23#define LM3533_CONTROL_BANK_ENABLE 0x27 24#define LM3533_OVP_FREQUENCY_PWM_POLARITY 0x2C 25#define LM3533_BRIGHTNESS_REGISTER_A 0x40 26 27struct lm3533_backlight_priv { 28 struct gpio_desc enable_gpio; 29 u32 def_bl_lvl; 30}; 31 32static int lm3533_backlight_enable(struct udevice *dev) 33{ 34 struct lm3533_backlight_priv *priv = dev_get_priv(dev); 35 int ret; 36 37 dm_gpio_set_value(&priv->enable_gpio, 1); 38 mdelay(5); 39 40 /* HVLED 1 & 2 are controlled by Bank A */ 41 ret = dm_i2c_reg_write(dev, LM3533_SINK_OUTPUT_CONFIG_1, 0x00); 42 if (ret) 43 return ret; 44 45 /* PWM input is disabled for CABC */ 46 ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_A_PWM, 0x00); 47 if (ret) 48 return ret; 49 50 /* Linear & Control Bank A is configured for register Current control */ 51 ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_AB_BRIGHTNESS, 0x02); 52 if (ret) 53 return ret; 54 55 /* Full-Scale Current (20.2mA) */ 56 ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_A_FULLSCALE_CURRENT, 0x13); 57 if (ret) 58 return ret; 59 60 /* Control Bank A is enable */ 61 ret = dm_i2c_reg_write(dev, LM3533_CONTROL_BANK_ENABLE, 0x01); 62 if (ret) 63 return ret; 64 65 ret = dm_i2c_reg_write(dev, LM3533_OVP_FREQUENCY_PWM_POLARITY, 0x0A); 66 if (ret) 67 return ret; 68 69 return 0; 70} 71 72static int lm3533_backlight_set_brightness(struct udevice *dev, int percent) 73{ 74 struct lm3533_backlight_priv *priv = dev_get_priv(dev); 75 int ret; 76 77 if (percent == BACKLIGHT_DEFAULT) 78 percent = priv->def_bl_lvl; 79 80 if (percent < LM3533_BL_MIN_BRIGHTNESS) 81 percent = LM3533_BL_MIN_BRIGHTNESS; 82 83 if (percent > LM3533_BL_MAX_BRIGHTNESS) 84 percent = LM3533_BL_MAX_BRIGHTNESS; 85 86 /* Set brightness level */ 87 ret = dm_i2c_reg_write(dev, LM3533_BRIGHTNESS_REGISTER_A, 88 percent); 89 if (ret) 90 return ret; 91 92 return 0; 93} 94 95static int lm3533_backlight_probe(struct udevice *dev) 96{ 97 struct lm3533_backlight_priv *priv = dev_get_priv(dev); 98 int ret; 99 100 if (device_get_uclass_id(dev->parent) != UCLASS_I2C) 101 return -EPROTONOSUPPORT; 102 103 ret = gpio_request_by_name(dev, "enable-gpios", 0, 104 &priv->enable_gpio, GPIOD_IS_OUT); 105 if (ret) { 106 log_err("Could not decode enable-gpios (%d)\n", ret); 107 return ret; 108 } 109 110 priv->def_bl_lvl = dev_read_u32_default(dev, "default-brightness-level", 111 LM3533_BL_MAX_BRIGHTNESS); 112 113 return 0; 114} 115 116static const struct backlight_ops lm3533_backlight_ops = { 117 .enable = lm3533_backlight_enable, 118 .set_brightness = lm3533_backlight_set_brightness, 119}; 120 121static const struct udevice_id lm3533_backlight_ids[] = { 122 { .compatible = "ti,lm3533" }, 123 { } 124}; 125 126U_BOOT_DRIVER(lm3533_backlight) = { 127 .name = "lm3533_backlight", 128 .id = UCLASS_PANEL_BACKLIGHT, 129 .of_match = lm3533_backlight_ids, 130 .probe = lm3533_backlight_probe, 131 .ops = &lm3533_backlight_ops, 132 .priv_auto = sizeof(struct lm3533_backlight_priv), 133}; 134