From bf2d1902f4c670fa5a4cfa88982aaf6ab6ee2688 Mon Sep 17 00:00:00 2001 From: Svyatoslav Ryhel Date: Wed, 2 Oct 2024 12:07:10 +0300 Subject: [PATCH] video: backlight: add Skyworks/Analogictech AAT2870 led controller driver Add support for Skyworks AAT2870 LED Backlight Driver and Multiple LDO Lighting Management Unit. Only backlight is supported as for now. Supported backlight level range is from 2 to 255 with step of 1. Tested-by: Ion Agorria Signed-off-by: Svyatoslav Ryhel --- drivers/video/Kconfig | 10 +++ drivers/video/Makefile | 1 + drivers/video/aat2870_backlight.c | 132 ++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 drivers/video/aat2870_backlight.c diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 2014090c178..dfe4b3b8a02 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -783,6 +783,16 @@ config ATMEL_HLCD help HLCDC supports video output to an attached LCD panel. +config BACKLIGHT_AAT2870 + bool "Backlight Driver for AAT2870" + depends on BACKLIGHT + select DM_I2C + help + Say Y to enable the backlight driver for Skyworks AAT2870 LED + Backlight Driver and Multiple LDO Lighting Management Unit. + Only backlight is supported as for now. Supported backlight + level range is from 2 to 255 with step of 1. + config BACKLIGHT_LM3532 bool "Backlight Driver for LM3532" depends on BACKLIGHT diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 277ed093a03..ebe4a3961fc 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_$(PHASE_)BMP) += bmp.o endif +obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_backlight.o obj-$(CONFIG_BACKLIGHT_LM3532) += lm3532_backlight.o obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_backlight.o obj-$(CONFIG_BACKLIGHT_LP855x) += lp855x_backlight.o diff --git a/drivers/video/aat2870_backlight.c b/drivers/video/aat2870_backlight.c new file mode 100644 index 00000000000..209d15b3639 --- /dev/null +++ b/drivers/video/aat2870_backlight.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024 Svyatoslav Ryhel + */ + +#define LOG_CATEGORY UCLASS_PANEL_BACKLIGHT + +#include +#include +#include +#include +#include +#include +#include + +#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), +}; -- 2.39.5