Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2024 Svyatoslav Ryhel <clamor95@gmail.com> */ #define LOG_CATEGORY UCLASS_PANEL_BACKLIGHT #include <backlight.h> #include <dm.h> #include <i2c.h> #include <log.h> #include <linux/err.h> #include <asm/gpio.h> #include <power/regulator.h> #define AAT2870_BL_MIN_BRIGHTNESS 0x01 #define AAT2870_BL_DEF_BRIGHTNESS 0x64 #define AAT2870_BL_MAX_BRIGHTNESS 0xff #define AAT2870_BL_CH_EN 0x00 #define AAT2870_BLM 0x01 #define AAT2870_BL_CH_ALL 0xff #define AAT2870_CURRENT_MAX 27900000 #define AAT2870_CURRENT_STEP 900000 struct aat2870_backlight_priv { struct gpio_desc enable_gpio; int channels; int max_current; }; static int aat2870_backlight_enable(struct udevice *dev) { struct aat2870_backlight_priv *priv = dev_get_priv(dev); int ret; dm_gpio_set_value(&priv->enable_gpio, 1); /* Enable backlight for defined set of channels */ ret = dm_i2c_reg_write(dev, AAT2870_BL_CH_EN, priv->channels); if (ret) return ret; return 0; } static int aat2870_backlight_set_brightness(struct udevice *dev, int percent) { struct aat2870_backlight_priv *priv = dev_get_priv(dev); int brightness, ret; if (percent == BACKLIGHT_DEFAULT) percent = AAT2870_BL_DEF_BRIGHTNESS; if (percent < AAT2870_BL_MIN_BRIGHTNESS) percent = AAT2870_BL_MIN_BRIGHTNESS; if (percent > AAT2870_BL_MAX_BRIGHTNESS) percent = AAT2870_BL_MAX_BRIGHTNESS; brightness = percent * priv->max_current; brightness /= AAT2870_BL_MAX_BRIGHTNESS; /* Set brightness level */ ret = dm_i2c_reg_write(dev, AAT2870_BLM, brightness); if (ret) return ret; return 0; } static int aat2870_backlight_of_to_plat(struct udevice *dev) { struct aat2870_backlight_priv *priv = dev_get_priv(dev); int ret; ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable_gpio, GPIOD_IS_OUT); if (ret) { log_err("%s: cannot get enable-gpios (%d)\n", __func__, ret); return ret; } /* Backlight is one of children but has no dedicated driver */ ofnode backlight = ofnode_find_subnode(dev_ofnode(dev), "backlight"); if (ofnode_valid(backlight) && ofnode_is_enabled(backlight)) { /* Number of channel is equal to bit number */ priv->channels = dev_read_u32_default(dev, "channels", AAT2870_BL_CH_ALL); if (priv->channels != AAT2870_BL_CH_ALL) priv->channels = BIT(priv->channels); /* 450mA - 27900mA range with a 900mA step */ priv->max_current = dev_read_u32_default(dev, "current-max-microamp", AAT2870_CURRENT_MAX); priv->max_current /= AAT2870_CURRENT_STEP; } return 0; } static int aat2870_backlight_probe(struct udevice *dev) { if (device_get_uclass_id(dev->parent) != UCLASS_I2C) return -EPROTONOSUPPORT; return 0; } static const struct backlight_ops aat2870_backlight_ops = { .enable = aat2870_backlight_enable, .set_brightness = aat2870_backlight_set_brightness, }; static const struct udevice_id aat2870_backlight_ids[] = { { .compatible = "analogictech,aat2870" }, { .compatible = "skyworks,aat2870" }, { } }; U_BOOT_DRIVER(aat2870_backlight) = { .name = "aat2870_backlight", .id = UCLASS_PANEL_BACKLIGHT, .of_match = aat2870_backlight_ids, .of_to_plat = aat2870_backlight_of_to_plat, .probe = aat2870_backlight_probe, .ops = &aat2870_backlight_ops, .priv_auto = sizeof(struct aat2870_backlight_priv), }; |