Commit b5a8c50e authored by Duje Mihanović's avatar Duje Mihanović Committed by Lee Jones

leds: ktd2692: Convert to use ExpressWire library

The KTD2692 uses the ExpressWire protocol implemented in the newly
introduced ExpressWire library. Convert the driver to use the library.
Suggested-by: default avatarDaniel Thompson <daniel.thompson@linaro.org>
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Reviewed-by: default avatarDaniel Thompson <daniel.thompson@linaro.org>
Signed-off-by: default avatarDuje Mihanović <duje.mihanovic@skole.hr>
Link: https://lore.kernel.org/r/20240125-ktd2801-v5-2-e22da232a825@skole.hrSigned-off-by: default avatarLee Jones <lee@kernel.org>
parent 1368d06d
...@@ -23,7 +23,7 @@ config LEDS_AS3645A ...@@ -23,7 +23,7 @@ config LEDS_AS3645A
config LEDS_KTD2692 config LEDS_KTD2692
tristate "LED support for Kinetic KTD2692 flash LED controller" tristate "LED support for Kinetic KTD2692 flash LED controller"
depends on OF depends on OF
depends on GPIOLIB || COMPILE_TEST select LEDS_EXPRESSWIRE
help help
This option enables support for Kinetic KTD2692 LED flash connected This option enables support for Kinetic KTD2692 LED flash connected
through ExpressWire interface. through ExpressWire interface.
......
...@@ -6,9 +6,9 @@ ...@@ -6,9 +6,9 @@
* Ingi Kim <ingi2.kim@samsung.com> * Ingi Kim <ingi2.kim@samsung.com>
*/ */
#include <linux/delay.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/leds-expresswire.h>
#include <linux/led-class-flash.h> #include <linux/led-class-flash.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h> #include <linux/mutex.h>
...@@ -37,22 +37,9 @@ ...@@ -37,22 +37,9 @@
#define KTD2692_REG_FLASH_CURRENT_BASE 0x80 #define KTD2692_REG_FLASH_CURRENT_BASE 0x80
#define KTD2692_REG_MODE_BASE 0xA0 #define KTD2692_REG_MODE_BASE 0xA0
/* Set bit coding time for expresswire interface */
#define KTD2692_TIME_RESET_US 700
#define KTD2692_TIME_DATA_START_TIME_US 10
#define KTD2692_TIME_HIGH_END_OF_DATA_US 350
#define KTD2692_TIME_LOW_END_OF_DATA_US 10
#define KTD2692_TIME_SHORT_BITSET_US 4
#define KTD2692_TIME_LONG_BITSET_US 12
/* KTD2692 default length of name */ /* KTD2692 default length of name */
#define KTD2692_NAME_LENGTH 20 #define KTD2692_NAME_LENGTH 20
enum ktd2692_bitset {
KTD2692_LOW = 0,
KTD2692_HIGH,
};
/* Movie / Flash Mode Control */ /* Movie / Flash Mode Control */
enum ktd2692_led_mode { enum ktd2692_led_mode {
KTD2692_MODE_DISABLE = 0, /* default */ KTD2692_MODE_DISABLE = 0, /* default */
...@@ -71,7 +58,19 @@ struct ktd2692_led_config_data { ...@@ -71,7 +58,19 @@ struct ktd2692_led_config_data {
enum led_brightness max_brightness; enum led_brightness max_brightness;
}; };
const struct expresswire_timing ktd2692_timing = {
.poweroff_us = 700,
.data_start_us = 10,
.end_of_data_low_us = 10,
.end_of_data_high_us = 350,
.short_bitset_us = 4,
.long_bitset_us = 12
};
struct ktd2692_context { struct ktd2692_context {
/* Common ExpressWire properties (ctrl GPIO and timing) */
struct expresswire_common_props props;
/* Related LED Flash class device */ /* Related LED Flash class device */
struct led_classdev_flash fled_cdev; struct led_classdev_flash fled_cdev;
...@@ -80,7 +79,6 @@ struct ktd2692_context { ...@@ -80,7 +79,6 @@ struct ktd2692_context {
struct regulator *regulator; struct regulator *regulator;
struct gpio_desc *aux_gpio; struct gpio_desc *aux_gpio;
struct gpio_desc *ctrl_gpio;
enum ktd2692_led_mode mode; enum ktd2692_led_mode mode;
enum led_brightness torch_brightness; enum led_brightness torch_brightness;
...@@ -92,67 +90,6 @@ static struct ktd2692_context *fled_cdev_to_led( ...@@ -92,67 +90,6 @@ static struct ktd2692_context *fled_cdev_to_led(
return container_of(fled_cdev, struct ktd2692_context, fled_cdev); return container_of(fled_cdev, struct ktd2692_context, fled_cdev);
} }
static void ktd2692_expresswire_start(struct ktd2692_context *led)
{
gpiod_direction_output(led->ctrl_gpio, KTD2692_HIGH);
udelay(KTD2692_TIME_DATA_START_TIME_US);
}
static void ktd2692_expresswire_reset(struct ktd2692_context *led)
{
gpiod_direction_output(led->ctrl_gpio, KTD2692_LOW);
udelay(KTD2692_TIME_RESET_US);
}
static void ktd2692_expresswire_end(struct ktd2692_context *led)
{
gpiod_direction_output(led->ctrl_gpio, KTD2692_LOW);
udelay(KTD2692_TIME_LOW_END_OF_DATA_US);
gpiod_direction_output(led->ctrl_gpio, KTD2692_HIGH);
udelay(KTD2692_TIME_HIGH_END_OF_DATA_US);
}
static void ktd2692_expresswire_set_bit(struct ktd2692_context *led, bool bit)
{
/*
* The Low Bit(0) and High Bit(1) is based on a time detection
* algorithm between time low and time high
* Time_(L_LB) : Low time of the Low Bit(0)
* Time_(H_LB) : High time of the LOW Bit(0)
* Time_(L_HB) : Low time of the High Bit(1)
* Time_(H_HB) : High time of the High Bit(1)
*
* It can be simplified to:
* Low Bit(0) : 2 * Time_(H_LB) < Time_(L_LB)
* High Bit(1) : 2 * Time_(L_HB) < Time_(H_HB)
* HIGH ___ ____ _.. _________ ___
* |_________| |_.. |____| |__|
* LOW <L_LB> <H_LB> <L_HB> <H_HB>
* [ Low Bit (0) ] [ High Bit(1) ]
*/
if (bit) {
gpiod_direction_output(led->ctrl_gpio, KTD2692_LOW);
udelay(KTD2692_TIME_SHORT_BITSET_US);
gpiod_direction_output(led->ctrl_gpio, KTD2692_HIGH);
udelay(KTD2692_TIME_LONG_BITSET_US);
} else {
gpiod_direction_output(led->ctrl_gpio, KTD2692_LOW);
udelay(KTD2692_TIME_LONG_BITSET_US);
gpiod_direction_output(led->ctrl_gpio, KTD2692_HIGH);
udelay(KTD2692_TIME_SHORT_BITSET_US);
}
}
static void ktd2692_expresswire_write(struct ktd2692_context *led, u8 value)
{
int i;
ktd2692_expresswire_start(led);
for (i = 7; i >= 0; i--)
ktd2692_expresswire_set_bit(led, value & BIT(i));
ktd2692_expresswire_end(led);
}
static int ktd2692_led_brightness_set(struct led_classdev *led_cdev, static int ktd2692_led_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brightness) enum led_brightness brightness)
{ {
...@@ -163,14 +100,14 @@ static int ktd2692_led_brightness_set(struct led_classdev *led_cdev, ...@@ -163,14 +100,14 @@ static int ktd2692_led_brightness_set(struct led_classdev *led_cdev,
if (brightness == LED_OFF) { if (brightness == LED_OFF) {
led->mode = KTD2692_MODE_DISABLE; led->mode = KTD2692_MODE_DISABLE;
gpiod_direction_output(led->aux_gpio, KTD2692_LOW); gpiod_direction_output(led->aux_gpio, 0);
} else { } else {
ktd2692_expresswire_write(led, brightness | expresswire_write_u8(&led->props, brightness |
KTD2692_REG_MOVIE_CURRENT_BASE); KTD2692_REG_MOVIE_CURRENT_BASE);
led->mode = KTD2692_MODE_MOVIE; led->mode = KTD2692_MODE_MOVIE;
} }
ktd2692_expresswire_write(led, led->mode | KTD2692_REG_MODE_BASE); expresswire_write_u8(&led->props, led->mode | KTD2692_REG_MODE_BASE);
mutex_unlock(&led->lock); mutex_unlock(&led->lock);
return 0; return 0;
...@@ -187,17 +124,17 @@ static int ktd2692_led_flash_strobe_set(struct led_classdev_flash *fled_cdev, ...@@ -187,17 +124,17 @@ static int ktd2692_led_flash_strobe_set(struct led_classdev_flash *fled_cdev,
if (state) { if (state) {
flash_tm_reg = GET_TIMEOUT_OFFSET(timeout->val, timeout->step); flash_tm_reg = GET_TIMEOUT_OFFSET(timeout->val, timeout->step);
ktd2692_expresswire_write(led, flash_tm_reg expresswire_write_u8(&led->props, flash_tm_reg
| KTD2692_REG_FLASH_TIMEOUT_BASE); | KTD2692_REG_FLASH_TIMEOUT_BASE);
led->mode = KTD2692_MODE_FLASH; led->mode = KTD2692_MODE_FLASH;
gpiod_direction_output(led->aux_gpio, KTD2692_HIGH); gpiod_direction_output(led->aux_gpio, 1);
} else { } else {
led->mode = KTD2692_MODE_DISABLE; led->mode = KTD2692_MODE_DISABLE;
gpiod_direction_output(led->aux_gpio, KTD2692_LOW); gpiod_direction_output(led->aux_gpio, 0);
} }
ktd2692_expresswire_write(led, led->mode | KTD2692_REG_MODE_BASE); expresswire_write_u8(&led->props, led->mode | KTD2692_REG_MODE_BASE);
fled_cdev->led_cdev.brightness = LED_OFF; fled_cdev->led_cdev.brightness = LED_OFF;
led->mode = KTD2692_MODE_DISABLE; led->mode = KTD2692_MODE_DISABLE;
...@@ -247,12 +184,12 @@ static void ktd2692_init_flash_timeout(struct led_classdev_flash *fled_cdev, ...@@ -247,12 +184,12 @@ static void ktd2692_init_flash_timeout(struct led_classdev_flash *fled_cdev,
static void ktd2692_setup(struct ktd2692_context *led) static void ktd2692_setup(struct ktd2692_context *led)
{ {
led->mode = KTD2692_MODE_DISABLE; led->mode = KTD2692_MODE_DISABLE;
ktd2692_expresswire_reset(led); expresswire_power_off(&led->props);
gpiod_direction_output(led->aux_gpio, KTD2692_LOW); gpiod_direction_output(led->aux_gpio, 0);
ktd2692_expresswire_write(led, (KTD2692_MM_MIN_CURR_THRESHOLD_SCALE - 1) expresswire_write_u8(&led->props, (KTD2692_MM_MIN_CURR_THRESHOLD_SCALE - 1)
| KTD2692_REG_MM_MIN_CURR_THRESHOLD_BASE); | KTD2692_REG_MM_MIN_CURR_THRESHOLD_BASE);
ktd2692_expresswire_write(led, KTD2692_FLASH_MODE_CURR_PERCENT(45) expresswire_write_u8(&led->props, KTD2692_FLASH_MODE_CURR_PERCENT(45)
| KTD2692_REG_FLASH_CURRENT_BASE); | KTD2692_REG_FLASH_CURRENT_BASE);
} }
...@@ -277,8 +214,8 @@ static int ktd2692_parse_dt(struct ktd2692_context *led, struct device *dev, ...@@ -277,8 +214,8 @@ static int ktd2692_parse_dt(struct ktd2692_context *led, struct device *dev,
if (!np) if (!np)
return -ENXIO; return -ENXIO;
led->ctrl_gpio = devm_gpiod_get(dev, "ctrl", GPIOD_ASIS); led->props.ctrl_gpio = devm_gpiod_get(dev, "ctrl", GPIOD_ASIS);
ret = PTR_ERR_OR_ZERO(led->ctrl_gpio); ret = PTR_ERR_OR_ZERO(led->props.ctrl_gpio);
if (ret) if (ret)
return dev_err_probe(dev, ret, "cannot get ctrl-gpios\n"); return dev_err_probe(dev, ret, "cannot get ctrl-gpios\n");
...@@ -412,6 +349,7 @@ static struct platform_driver ktd2692_driver = { ...@@ -412,6 +349,7 @@ static struct platform_driver ktd2692_driver = {
module_platform_driver(ktd2692_driver); module_platform_driver(ktd2692_driver);
MODULE_IMPORT_NS(EXPRESSWIRE);
MODULE_AUTHOR("Ingi Kim <ingi2.kim@samsung.com>"); MODULE_AUTHOR("Ingi Kim <ingi2.kim@samsung.com>");
MODULE_DESCRIPTION("Kinetic KTD2692 LED driver"); MODULE_DESCRIPTION("Kinetic KTD2692 LED driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment