root/drivers/leds/rgb/leds-lp5860.h
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2025 Pengutronix
 *
 * Author: Steffen Trumtrar <kernel@pengutronix.de>
 */

#ifndef _DRIVERS_LEDS_RGB_LP5860_H
#define _DRIVERS_LEDS_RGB_LP5860_H

#include <linux/led-class-multicolor.h>
#include <linux/regmap.h>

#define LP5860_REG_CHIP_EN              0x00
#define LP5860_REG_DEV_INITIAL          0x01
#define LP5860_REG_DEV_CONFIG1          0x02
#define LP5860_REG_DEV_CONFIG2          0x03
#define LP5860_REG_DEV_CONFIG3          0x04
#define LP5860_REG_GLOBAL_BRI           0x05
#define LP5860_REG_GROUP0_BRI           0x06
#define LP5860_REG_GROUP1_BRI           0x07
#define LP5860_REG_GROUP2_BRI           0x08
#define LP5860_REG_R_CURRENT_SET        0x09
#define LP5860_REG_G_CURRENT_SET        0x0A
#define LP5860_REG_B_CURRENT_SET        0x0B
#define LP5860_REG_GRP_SEL_START        0x0C
#define LP5860_REG_DOT_ONOFF_START      0x43
#define LP5860_REG_DOT_ONOFF_MAX        0x63
#define LP5860_REG_FAULT_STATE          0x64
#define LP5860_REG_DOT_LOD_START        0x65
#define LP5860_REG_DOT_LSD_START        0x86
#define LP5860_REG_LOD_CLEAR            0xA7
#define LP5860_REG_LSD_CLEAR            0xA8
#define LP5860_REG_RESET                0xA9
#define LP5860_REG_DC_START             0x0100
#define LP5860_REG_PWM_BRI_START        0x0200
#define LP5860_MAX_REG                  0x038B

/* Register chip_enable value */
#define LP5860_CHIP_SHIFT               0
#define LP5860_CHIP_MASK                BIT(0)
#define LP5860_CHIP_DISABLE             false
#define LP5860_CHIP_ENABLE              true

/* Register dev_initial value */
#define LP5860_MAX_LINE_SHIFT           3
#define LP5860_MAX_LINE_MASK            GENMASK(6, 3)
#define LP5860_MAX_LINE_11              0x0B
#define LP5860_MAX_LINE_10              0x0A
#define LP5860_MAX_LINE_9               0x09
#define LP5860_MAX_LINE_8               0x08
#define LP5860_MAX_LINE_7               0x07
#define LP5860_MAX_LINE_6               0x06
#define LP5860_MAX_LINE_5               0x05
#define LP5860_MAX_LINE_4               0x04
#define LP5860_MAX_LINE_3               0x03
#define LP5860_MAX_LINE_2               0x02
#define LP5860_MAX_LINE_1               0x01

#define LP5860_MODE_SHIFT               1
#define LP5860_MODE_MASK                GENMASK(2, 1)
#define LP5860_MODE_3_1                 0x03
#define LP5860_MODE_3                   0x02
#define LP5860_MODE_2                   0x01
#define LP5860_MODE_1                   0x00

#define LP5860_PWM_FREQUENCY_SHIFT      0
#define LP5860_PWM_FREQUENCY_MASK       BIT(0)
#define LP5860_PWM_FREQUENCY_62_5K      0x01
#define LP5860_PWM_FREQUENCY_125K       0x00

/* Register dev_config1 value */
#define LP5860_SW_BLK_SHIFT             3
#define LP5860_SW_BLK_MASK              BIT(3)
#define LP5860_SW_BLK_05US              0x01
#define LP5860_SW_BLK_1US               0x00

#define LP5860_PWM_SCALE_MODE_SHIFT     2
#define LP5860_PWM_SCALE_MODE_MASK      BIT(2)
#define LP5860_PWM_SCALE_EXPONENTIAL    0x01
#define LP5860_PWM_SCALE_LINEAR         0x00

#define LP5860_PWM_PHASESHIFT_SHIFT     1
#define LP5860_PWM_PHASESHIFT_MASK      BIT(1)
#define LP5860_PWM_PHASESHIFT_ON        0x01
#define LP5860_PWM_PHASESHIFT_OFF       0x00

#define LP5860_CS_ON_SHIFT_SHIFT        0
#define LP5860_CS_ON_SHIFT_MASK         BIT(0)
#define LP5860_CS_DELAY_ON              0x01
#define LP5860_CS_DELAY_OFF             0x00

/* Register dev_config2 value */
#define LP5860_COMP_GROUP3_SHIFT        6
#define LP5860_COMP_GROUP3_MASK         GENMASK(7, 6)
#define LP5860_COMP_GROUP3_3CLOCK       0x03
#define LP5860_COMP_GROUP3_2CLOCK       0x02
#define LP5860_COMP_GROUP3_1CLOCK       0x01
#define LP5860_COMP_GROUP3_OFF          0x00

#define LP5860_COMP_GROUP2_SHIFT        4
#define LP5860_COMP_GROUP2_MASK         GENMASK(5, 4)
#define LP5860_COMP_GROUP2_3CLOCK       0x03
#define LP5860_COMP_GROUP2_2CLOCK       0x02
#define LP5860_COMP_GROUP2_1CLOCK       0x01
#define LP5860_COMP_GROUP2_OFF          0x00

#define LP5860_COMP_GROUP1_SHIFT        2
#define LP5860_COMP_GROUP1_MASK         GENMASK(3, 2)
#define LP5860_COMP_GROUP1_3CLOCK       0x03
#define LP5860_COMP_GROUP1_2CLOCK       0x02
#define LP5860_COMP_GROUP1_1CLOCK       0x01
#define LP5860_COMP_GROUP1_OFF          0x00

#define LP5860_LOD_REMOVAL_SHIFT        1
#define LP5860_LOD_REMOVAL_MASK         BIT(1)
#define LP5860_LOD_REMOVAL_EN           0x01
#define LP5860_LOD_REMOVAL_OFF          0x00

#define LP5860_LSD_REMOVAL_SHIFT        0
#define LP5860_LSD_REMOVAL_MASK         BIT(0)
#define LP5860_LSD_REMOVAL_EN           0x01
#define LP5860_LSD_REMOVAL_OFF          0x00

/* Register dev_config3 value */
#define LP5860_DOWN_DEGHOST_SHIFT       6
#define LP5860_DOWN_DEGHOST_MASK        GENMASK(7, 6)
#define LP5860_DOWN_DEGHOST_STRONG      0x03
#define LP5860_DOWN_DEGHOST_MEDIUM      0x02
#define LP5860_DOWN_DEGHOST_WEAK        0x01
#define LP5860_DOWN_DEGHOST_OFF         0x00

#define LP5860_UP_DEGHOST_SHIFT 4
#define LP5860_UP_DEGHOST_MASK          GENMASK(5, 4)
#define LP5860_UP_DEGHOST_GND           0x03
#define LP5860_UP_DEGHOST_3             0x02
#define LP5860_UP_DEGHOST_2_5           0x01
#define LP5860_UP_DEGHOST_2             0x00

#define LP5860_MAXIMUM_CURRENT_SHIFT    1
#define LP5860_MAXIMUM_CURRENT_MASK     GENMASK(3, 1)
#define LP5860_MAXIMUM_CURRENT_50       0x07
#define LP5860_MAXIMUM_CURRENT_40       0x06
#define LP5860_MAXIMUM_CURRENT_30       0x05
#define LP5860_MAXIMUM_CURRENT_20       0x04
#define LP5860_MAXIMUM_CURRENT_15       0x03
#define LP5860_MAXIMUM_CURRENT_10       0x02
#define LP5860_MAXIMUM_CURRENT_5        0x01
#define LP5860_MAXIMUM_CURRENT_3        0x00

#define LP5860_UP_DEGHOST_ENABLE_SHIFT  0
#define LP5860_UP_DEGHOST_ENABLE_MASK   BIT(0)
#define LP5860_UP_DEGHOST_ENABLE_EN     0x01
#define LP5860_UP_DEGHOST_ENABLE_OFF    0x00

/* Register PWM */
#define LP5860_PWM_GLOBAL_MAX           0xff
#define LP5860_PWM_GROUP_MAX            0xff

/* Register CC group select */
#define LP5860_CC_GROUP_MASK            GENMASK(7, 0)
#define LP5860_CC_GROUP_MAX             0x7F

/* Register dot group select */
#define LP5860_DOT_0_SHIFT              0
#define LP5860_DOT_1_SHIFT              2
#define LP5860_DOT_2_SHIFT              4
#define LP5860_DOT_3_SHIFT              6

#define LP5860_DOT_GROUP3               0x03
#define LP5860_DOT_GROUP2               0x02
#define LP5860_DOT_GROUP1               0x01
#define LP5860_DOT_GROUP_NONE           0x00

#define LP5860_DOT_ALL_ON               0xff
#define LP5860_DOT_ALL_OFF              0x0
#define LP5860_PWM_DOT_MAX              0xff
/* Dot onoff value */
#define LP5860_DOT_CS0_SHIFT            0
#define LP5860_DOT_CS1_SHIFT            1
#define LP5860_DOT_CS2_SHIFT            2
#define LP5860_DOT_CS3_SHIFT            3
#define LP5860_DOT_CS4_SHIFT            4
#define LP5860_DOT_CS5_SHIFT            5
#define LP5860_DOT_CS6_SHIFT            6
#define LP5860_DOT_CS7_SHIFT            7

#define LP5860_DOT_CS_ON                0x01
#define LP5860_DOT_CS_OFF               0x00

/* Dot lod value */
#define LP5860_DOT_LOD0_SHIFT           0
#define LP5860_DOT_LOD1_SHIFT           1
#define LP5860_DOT_LOD2_SHIFT           2
#define LP5860_DOT_LOD3_SHIFT           3
#define LP5860_DOT_LOD4_SHIFT           4
#define LP5860_DOT_LOD5_SHIFT           5
#define LP5860_DOT_LOD6_SHIFT           6
#define LP5860_DOT_LOD7_SHIFT           7

#define LP5860_DOT_LOD_ON               0x01
#define LP5860_DOT_LOD_OFF              0x00

/* dot lsd value */
#define LP5860_DOT_LSD0_SHIFT           0
#define LP5860_DOT_LSD1_SHIFT           1
#define LP5860_DOT_LSD2_SHIFT           2
#define LP5860_DOT_LSD3_SHIFT           3
#define LP5860_DOT_LSD4_SHIFT           4
#define LP5860_DOT_LSD5_SHIFT           5
#define LP5860_DOT_LSD6_SHIFT           6
#define LP5860_DOT_LSD7_SHIFT           7

#define LP5860_DOT_LSD_ON               0x01
#define LP5860_DOT_LSD_OFF              0x00

/* Register lod state */
#define LP5860_GLOBAL_LOD_SHIFT 1
#define LP5860_GLOBAL_LOD_STATE         BIT(1)
#define LP5860_GLOBAL_LSD_SHIFT 0
#define LP5860_GLOBAL_LSD_STATE         BIT(0)

#define LP5860_FAULT_STATE_ON           0x01
#define LP5860_FAULT_STATE_OFF          0x00

#define LP5860_GLOBAL_LOD_CLEAR         0x00
#define LP5860_GLOBAL_LSD_CLEAR         0x00


#define LP5860_LOD_CLEAR_EN             0xff
#define LP5860_LSD_CLEAR_EN             0xff
#define LP5860_RESET_EN                 0xff

#define LP5860_MAX_BRIGHTNESS           255
#define LP5860_REG_R_PWM                0x0
#define LP5860_REG_G_PWM                0x1
#define LP5860_REG_B_PWM                0x2

#define LP5860_MAX_LED_CONSTANT         18
#define LP5860_MAX_LED_SCAN             11
#define LP5860_MAX_LED                  (LP5860_MAX_LED_CONSTANT * LP5860_MAX_LED_SCAN)

#define LP5860_MAX_DOT_ONOFF_GROUP_NUM  8

/*
 * Theoretically, there is no max channel per LED,
 * limit this to a reasonable value for RGBW LEDs
 */
#define LP5860_MAX_LED_CHANNELS         4

struct lp5860_led {
        struct lp5860 *chip;
        struct led_classdev_mc mc_cdev;
        u8 brightness;
};

struct lp5860 {
        struct device *dev;
        struct regmap *regmap;
        struct mutex lock;

        DECLARE_FLEX_ARRAY(struct lp5860_led, leds);
};

int lp5860_device_init(struct device *dev);
void lp5860_device_remove(struct device *dev);

#endif /* _DRIVERS_LEDS_RGB_LP5860_H */