^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // TI LP50XX LED chip family driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Copyright (C) 2018-20 Texas Instruments Incorporated - https://www.ti.com/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/leds.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of_gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <uapi/linux/uleds.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/led-class-multicolor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "leds.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define LP50XX_DEV_CFG0 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define LP50XX_DEV_CFG1 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define LP50XX_LED_CFG0 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* LP5009 and LP5012 registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define LP5012_BNK_BRT 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define LP5012_BNKA_CLR 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define LP5012_BNKB_CLR 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define LP5012_BNKC_CLR 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define LP5012_LED0_BRT 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define LP5012_OUT0_CLR 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define LP5012_RESET 0x17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* LP5018 and LP5024 registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define LP5024_BNK_BRT 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define LP5024_BNKA_CLR 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define LP5024_BNKB_CLR 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define LP5024_BNKC_CLR 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define LP5024_LED0_BRT 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define LP5024_OUT0_CLR 0x0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define LP5024_RESET 0x27
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* LP5030 and LP5036 registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define LP5036_LED_CFG1 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define LP5036_BNK_BRT 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define LP5036_BNKA_CLR 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define LP5036_BNKB_CLR 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define LP5036_BNKC_CLR 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define LP5036_LED0_BRT 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define LP5036_OUT0_CLR 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define LP5036_RESET 0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define LP50XX_SW_RESET 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define LP50XX_CHIP_EN BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* There are 3 LED outputs per bank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define LP50XX_LEDS_PER_MODULE 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define LP5009_MAX_LED_MODULES 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define LP5012_MAX_LED_MODULES 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define LP5018_MAX_LED_MODULES 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define LP5024_MAX_LED_MODULES 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define LP5030_MAX_LED_MODULES 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define LP5036_MAX_LED_MODULES 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static const struct reg_default lp5012_reg_defs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {LP50XX_DEV_CFG0, 0x0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {LP50XX_DEV_CFG1, 0x3c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {LP50XX_LED_CFG0, 0x0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {LP5012_BNK_BRT, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {LP5012_BNKA_CLR, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {LP5012_BNKB_CLR, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {LP5012_BNKC_CLR, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {LP5012_LED0_BRT, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* LEDX_BRT registers are all 0xff for defaults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {0x08, 0xff}, {0x09, 0xff}, {0x0a, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {LP5012_OUT0_CLR, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* OUTX_CLR registers are all 0x0 for defaults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00}, {0x10, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00}, {0x14, 0x00}, {0x15, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {0x16, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {LP5012_RESET, 0x00}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static const struct reg_default lp5024_reg_defs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {LP50XX_DEV_CFG0, 0x0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {LP50XX_DEV_CFG1, 0x3c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {LP50XX_LED_CFG0, 0x0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {LP5024_BNK_BRT, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {LP5024_BNKA_CLR, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {LP5024_BNKB_CLR, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {LP5024_BNKC_CLR, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {LP5024_LED0_BRT, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* LEDX_BRT registers are all 0xff for defaults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {0x08, 0xff}, {0x09, 0xff}, {0x0a, 0xff}, {0x0b, 0xff}, {0x0c, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {0x0d, 0xff}, {0x0e, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {LP5024_OUT0_CLR, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* OUTX_CLR registers are all 0x0 for defaults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00}, {0x14, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00}, {0x18, 0x00}, {0x19, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {0x1a, 0x00}, {0x1b, 0x00}, {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {0x1f, 0x00}, {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {LP5024_RESET, 0x00}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static const struct reg_default lp5036_reg_defs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {LP50XX_DEV_CFG0, 0x0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {LP50XX_DEV_CFG1, 0x3c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {LP50XX_LED_CFG0, 0x0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {LP5036_LED_CFG1, 0x0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {LP5036_BNK_BRT, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {LP5036_BNKA_CLR, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {LP5036_BNKB_CLR, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {LP5036_BNKC_CLR, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {LP5036_LED0_BRT, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* LEDX_BRT registers are all 0xff for defaults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {0x08, 0xff}, {0x09, 0xff}, {0x0a, 0xff}, {0x0b, 0xff}, {0x0c, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {0x0d, 0xff}, {0x0e, 0xff}, {0x0f, 0xff}, {0x10, 0xff}, {0x11, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {0x12, 0xff}, {0x13, 0xff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {LP5036_OUT0_CLR, 0x0f},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* OUTX_CLR registers are all 0x0 for defaults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00}, {0x18, 0x00}, {0x19, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {0x1a, 0x00}, {0x1b, 0x00}, {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {0x1f, 0x00}, {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00}, {0x2c, 0x00}, {0x2d, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {0x2e, 0x00}, {0x2f, 0x00}, {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {0x33, 0x00}, {0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {LP5036_RESET, 0x00}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static const struct regmap_config lp5012_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .max_register = LP5012_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .reg_defaults = lp5012_reg_defs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .num_reg_defaults = ARRAY_SIZE(lp5012_reg_defs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .cache_type = REGCACHE_FLAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static const struct regmap_config lp5024_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .max_register = LP5024_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .reg_defaults = lp5024_reg_defs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .num_reg_defaults = ARRAY_SIZE(lp5024_reg_defs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .cache_type = REGCACHE_FLAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static const struct regmap_config lp5036_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .max_register = LP5036_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .reg_defaults = lp5036_reg_defs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .num_reg_defaults = ARRAY_SIZE(lp5036_reg_defs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .cache_type = REGCACHE_FLAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) enum lp50xx_model {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) LP5009,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) LP5012,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) LP5018,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) LP5024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) LP5030,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) LP5036,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * struct lp50xx_chip_info -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * @lp50xx_regmap_config: regmap register configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * @model_id: LED device model
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * @max_modules: total number of supported LED modules
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * @num_leds: number of LED outputs available on the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * @led_brightness0_reg: first brightness register of the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * @mix_out0_reg: first color mix register of the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * @bank_brt_reg: bank brightness register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * @bank_mix_reg: color mix register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * @reset_reg: device reset register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct lp50xx_chip_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) const struct regmap_config *lp50xx_regmap_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) int model_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) u8 max_modules;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) u8 num_leds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) u8 led_brightness0_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) u8 mix_out0_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) u8 bank_brt_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) u8 bank_mix_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) u8 reset_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static const struct lp50xx_chip_info lp50xx_chip_info_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) [LP5009] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .model_id = LP5009,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .max_modules = LP5009_MAX_LED_MODULES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) .num_leds = LP5009_MAX_LED_MODULES * LP50XX_LEDS_PER_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .led_brightness0_reg = LP5012_LED0_BRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .mix_out0_reg = LP5012_OUT0_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .bank_brt_reg = LP5012_BNK_BRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) .bank_mix_reg = LP5012_BNKA_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .reset_reg = LP5012_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .lp50xx_regmap_config = &lp5012_regmap_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) [LP5012] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .model_id = LP5012,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .max_modules = LP5012_MAX_LED_MODULES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .num_leds = LP5012_MAX_LED_MODULES * LP50XX_LEDS_PER_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .led_brightness0_reg = LP5012_LED0_BRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .mix_out0_reg = LP5012_OUT0_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .bank_brt_reg = LP5012_BNK_BRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .bank_mix_reg = LP5012_BNKA_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .reset_reg = LP5012_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .lp50xx_regmap_config = &lp5012_regmap_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) [LP5018] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .model_id = LP5018,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .max_modules = LP5018_MAX_LED_MODULES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .num_leds = LP5018_MAX_LED_MODULES * LP50XX_LEDS_PER_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .led_brightness0_reg = LP5024_LED0_BRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .mix_out0_reg = LP5024_OUT0_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) .bank_brt_reg = LP5024_BNK_BRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) .bank_mix_reg = LP5024_BNKA_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .reset_reg = LP5024_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .lp50xx_regmap_config = &lp5024_regmap_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) [LP5024] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) .model_id = LP5024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .max_modules = LP5024_MAX_LED_MODULES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .num_leds = LP5024_MAX_LED_MODULES * LP50XX_LEDS_PER_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) .led_brightness0_reg = LP5024_LED0_BRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .mix_out0_reg = LP5024_OUT0_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .bank_brt_reg = LP5024_BNK_BRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) .bank_mix_reg = LP5024_BNKA_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) .reset_reg = LP5024_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .lp50xx_regmap_config = &lp5024_regmap_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) [LP5030] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .model_id = LP5030,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .max_modules = LP5030_MAX_LED_MODULES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .num_leds = LP5030_MAX_LED_MODULES * LP50XX_LEDS_PER_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .led_brightness0_reg = LP5036_LED0_BRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) .mix_out0_reg = LP5036_OUT0_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .bank_brt_reg = LP5036_BNK_BRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) .bank_mix_reg = LP5036_BNKA_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) .reset_reg = LP5036_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .lp50xx_regmap_config = &lp5036_regmap_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) [LP5036] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .model_id = LP5036,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .max_modules = LP5036_MAX_LED_MODULES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .num_leds = LP5036_MAX_LED_MODULES * LP50XX_LEDS_PER_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .led_brightness0_reg = LP5036_LED0_BRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .mix_out0_reg = LP5036_OUT0_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .bank_brt_reg = LP5036_BNK_BRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .bank_mix_reg = LP5036_BNKA_CLR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .reset_reg = LP5036_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .lp50xx_regmap_config = &lp5036_regmap_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct lp50xx_led {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct led_classdev_mc mc_cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct lp50xx *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) unsigned long bank_modules;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) int led_intensity[LP50XX_LEDS_PER_MODULE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) u8 ctrl_bank_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) int led_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * struct lp50xx -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * @enable_gpio: hardware enable gpio
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * @regulator: LED supply regulator pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * @client: pointer to the I2C client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * @regmap: device register map
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * @dev: pointer to the devices device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * @lock: lock for reading/writing the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * @chip_info: chip specific information (ie num_leds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * @num_of_banked_leds: holds the number of banked LEDs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * @leds: array of LED strings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) struct lp50xx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct gpio_desc *enable_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct regulator *regulator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) const struct lp50xx_chip_info *chip_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) int num_of_banked_leds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /* This needs to be at the end of the struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) struct lp50xx_led leds[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static struct lp50xx_led *mcled_cdev_to_led(struct led_classdev_mc *mc_cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return container_of(mc_cdev, struct lp50xx_led, mc_cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static int lp50xx_brightness_set(struct led_classdev *cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) enum led_brightness brightness)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct led_classdev_mc *mc_dev = lcdev_to_mccdev(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) struct lp50xx_led *led = mcled_cdev_to_led(mc_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) const struct lp50xx_chip_info *led_chip = led->priv->chip_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) u8 led_offset, reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) mutex_lock(&led->priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (led->ctrl_bank_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) reg_val = led_chip->bank_brt_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) reg_val = led_chip->led_brightness0_reg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) led->led_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) ret = regmap_write(led->priv->regmap, reg_val, brightness);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) dev_err(&led->priv->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) "Cannot write brightness value %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) for (i = 0; i < led->mc_cdev.num_colors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (led->ctrl_bank_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) reg_val = led_chip->bank_mix_reg + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) led_offset = (led->led_number * 3) + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) reg_val = led_chip->mix_out0_reg + led_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) ret = regmap_write(led->priv->regmap, reg_val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) mc_dev->subled_info[i].intensity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) dev_err(&led->priv->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) "Cannot write intensity value %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) mutex_unlock(&led->priv->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static int lp50xx_set_banks(struct lp50xx *priv, u32 led_banks[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) u8 led_config_lo, led_config_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) u32 bank_enable_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) for (i = 0; i < priv->chip_info->max_modules; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (led_banks[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) bank_enable_mask |= (1 << led_banks[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) led_config_lo = (u8)(bank_enable_mask & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) led_config_hi = (u8)(bank_enable_mask >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) ret = regmap_write(priv->regmap, LP50XX_LED_CFG0, led_config_lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (priv->chip_info->model_id >= LP5030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ret = regmap_write(priv->regmap, LP5036_LED_CFG1, led_config_hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static int lp50xx_reset(struct lp50xx *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return regmap_write(priv->regmap, priv->chip_info->reset_reg, LP50XX_SW_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static int lp50xx_enable_disable(struct lp50xx *priv, int enable_disable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (priv->enable_gpio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) ret = gpiod_direction_output(priv->enable_gpio, enable_disable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (enable_disable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return regmap_write(priv->regmap, LP50XX_DEV_CFG0, LP50XX_CHIP_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return regmap_write(priv->regmap, LP50XX_DEV_CFG0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) static int lp50xx_probe_leds(struct fwnode_handle *child, struct lp50xx *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct lp50xx_led *led, int num_leds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) u32 led_banks[LP5036_MAX_LED_MODULES] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) int led_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (num_leds > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (num_leds > priv->chip_info->max_modules) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) dev_err(&priv->client->dev, "reg property is invalid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) priv->num_of_banked_leds = num_leds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) ret = fwnode_property_read_u32_array(child, "reg", led_banks, num_leds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) dev_err(&priv->client->dev, "reg property is missing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) ret = lp50xx_set_banks(priv, led_banks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) dev_err(&priv->client->dev, "Cannot setup banked LEDs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) led->ctrl_bank_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) ret = fwnode_property_read_u32(child, "reg", &led_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) dev_err(&priv->client->dev, "led reg property missing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (led_number > priv->chip_info->num_leds) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) dev_err(&priv->client->dev, "led-sources property is invalid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) led->led_number = led_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) static int lp50xx_probe_dt(struct lp50xx *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) struct fwnode_handle *child = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) struct fwnode_handle *led_node = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct led_init_data init_data = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct led_classdev *led_cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct mc_subled *mc_led_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) struct lp50xx_led *led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) int num_colors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) u32 color_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) priv->enable_gpio = devm_gpiod_get_optional(priv->dev, "enable", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (IS_ERR(priv->enable_gpio)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) ret = PTR_ERR(priv->enable_gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) dev_err(&priv->client->dev, "Failed to get enable gpio: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) priv->regulator = devm_regulator_get(priv->dev, "vled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (IS_ERR(priv->regulator))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) priv->regulator = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) device_for_each_child_node(priv->dev, child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) led = &priv->leds[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) ret = fwnode_property_count_u32(child, "reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) dev_err(&priv->client->dev, "reg property is invalid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) goto child_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) ret = lp50xx_probe_leds(child, priv, led, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) goto child_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) init_data.fwnode = child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) num_colors = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * There are only 3 LEDs per module otherwise they should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * banked which also is presented as 3 LEDs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) mc_led_info = devm_kcalloc(priv->dev, LP50XX_LEDS_PER_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) sizeof(*mc_led_info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (!mc_led_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) goto child_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) fwnode_for_each_child_node(child, led_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) ret = fwnode_property_read_u32(led_node, "color",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) &color_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) fwnode_handle_put(led_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) dev_err(priv->dev, "Cannot read color\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) goto child_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) mc_led_info[num_colors].color_index = color_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) num_colors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) led->priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) led->mc_cdev.num_colors = num_colors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) led->mc_cdev.subled_info = mc_led_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) led_cdev = &led->mc_cdev.led_cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) led_cdev->brightness_set_blocking = lp50xx_brightness_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) ret = devm_led_classdev_multicolor_register_ext(&priv->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) &led->mc_cdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) &init_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) dev_err(&priv->client->dev, "led register err: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) goto child_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) child_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) fwnode_handle_put(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) static int lp50xx_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct lp50xx *led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) count = device_get_child_node_count(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (!count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) dev_err(&client->dev, "LEDs are not defined in device tree!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) led = devm_kzalloc(&client->dev, struct_size(led, leds, count),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (!led)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) mutex_init(&led->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) led->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) led->dev = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) led->chip_info = &lp50xx_chip_info_tbl[id->driver_data];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) i2c_set_clientdata(client, led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) led->regmap = devm_regmap_init_i2c(client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) led->chip_info->lp50xx_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (IS_ERR(led->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) ret = PTR_ERR(led->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) dev_err(&client->dev, "Failed to allocate register map: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) ret = lp50xx_reset(led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) ret = lp50xx_enable_disable(led, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return lp50xx_probe_dt(led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) static int lp50xx_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct lp50xx *led = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) ret = lp50xx_enable_disable(led, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) dev_err(&led->client->dev, "Failed to disable chip\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (led->regulator) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) ret = regulator_disable(led->regulator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) dev_err(&led->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) "Failed to disable regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) mutex_destroy(&led->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) static const struct i2c_device_id lp50xx_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) { "lp5009", LP5009 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) { "lp5012", LP5012 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) { "lp5018", LP5018 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) { "lp5024", LP5024 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) { "lp5030", LP5030 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) { "lp5036", LP5036 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) MODULE_DEVICE_TABLE(i2c, lp50xx_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static const struct of_device_id of_lp50xx_leds_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) { .compatible = "ti,lp5009", .data = (void *)LP5009 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) { .compatible = "ti,lp5012", .data = (void *)LP5012 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) { .compatible = "ti,lp5018", .data = (void *)LP5018 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) { .compatible = "ti,lp5024", .data = (void *)LP5024 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) { .compatible = "ti,lp5030", .data = (void *)LP5030 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) { .compatible = "ti,lp5036", .data = (void *)LP5036 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) MODULE_DEVICE_TABLE(of, of_lp50xx_leds_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) static struct i2c_driver lp50xx_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) .name = "lp50xx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) .of_match_table = of_lp50xx_leds_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) .probe = lp50xx_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) .remove = lp50xx_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) .id_table = lp50xx_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) module_i2c_driver(lp50xx_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) MODULE_DESCRIPTION("Texas Instruments LP50XX LED driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) MODULE_LICENSE("GPL v2");