diff options
-rw-r--r-- | drivers/leds/leds-lp5523.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index b50948060a0..29c8b19a445 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c @@ -49,6 +49,9 @@ #define LP5523_REG_RESET 0x3D #define LP5523_REG_LED_TEST_CTRL 0x41 #define LP5523_REG_LED_TEST_ADC 0x42 +#define LP5523_REG_CH1_PROG_START 0x4C +#define LP5523_REG_CH2_PROG_START 0x4D +#define LP5523_REG_CH3_PROG_START 0x4E #define LP5523_REG_PROG_PAGE_SEL 0x4F #define LP5523_REG_PROG_MEM 0x50 @@ -65,6 +68,7 @@ #define LP5523_RESET 0xFF #define LP5523_ADC_SHORTCIRC_LIM 80 #define LP5523_EXT_CLK_USED 0x08 +#define LP5523_ENG_STATUS_MASK 0x07 /* Memory Page Selection */ #define LP5523_PAGE_ENG1 0 @@ -99,6 +103,8 @@ enum lp5523_chip_id { LP55231, }; +static int lp5523_init_program_engine(struct lp55xx_chip *chip); + static inline void lp5523_wait_opmode_done(void) { usleep_range(1000, 2000); @@ -134,7 +140,11 @@ static int lp5523_post_init_device(struct lp55xx_chip *chip) if (ret) return ret; - return lp55xx_write(chip, LP5523_REG_ENABLE_LEDS_LSB, 0xff); + ret = lp55xx_write(chip, LP5523_REG_ENABLE_LEDS_LSB, 0xff); + if (ret) + return ret; + + return lp5523_init_program_engine(chip); } static void lp5523_load_engine(struct lp55xx_chip *chip) @@ -233,6 +243,64 @@ static void lp5523_run_engine(struct lp55xx_chip *chip, bool start) lp55xx_update_bits(chip, LP5523_REG_ENABLE, LP5523_EXEC_M, exec); } +static int lp5523_init_program_engine(struct lp55xx_chip *chip) +{ + int i; + int j; + int ret; + u8 status; + /* one pattern per engine setting LED MUX start and stop addresses */ + static const u8 pattern[][LP5523_PROGRAM_LENGTH] = { + { 0x9c, 0x30, 0x9c, 0xb0, 0x9d, 0x80, 0xd8, 0x00, 0}, + { 0x9c, 0x40, 0x9c, 0xc0, 0x9d, 0x80, 0xd8, 0x00, 0}, + { 0x9c, 0x50, 0x9c, 0xd0, 0x9d, 0x80, 0xd8, 0x00, 0}, + }; + + /* hardcode 32 bytes of memory for each engine from program memory */ + ret = lp55xx_write(chip, LP5523_REG_CH1_PROG_START, 0x00); + if (ret) + return ret; + + ret = lp55xx_write(chip, LP5523_REG_CH2_PROG_START, 0x10); + if (ret) + return ret; + + ret = lp55xx_write(chip, LP5523_REG_CH3_PROG_START, 0x20); + if (ret) + return ret; + + /* write LED MUX address space for each engine */ + for (i = LP55XX_ENGINE_1; i <= LP55XX_ENGINE_3; i++) { + chip->engine_idx = i; + lp5523_load_engine_and_select_page(chip); + + for (j = 0; j < LP5523_PROGRAM_LENGTH; j++) { + ret = lp55xx_write(chip, LP5523_REG_PROG_MEM + j, + pattern[i - 1][j]); + if (ret) + goto out; + } + } + + lp5523_run_engine(chip, true); + + /* Let the programs run for couple of ms and check the engine status */ + usleep_range(3000, 6000); + lp55xx_read(chip, LP5523_REG_STATUS, &status); + status &= LP5523_ENG_STATUS_MASK; + + if (status != LP5523_ENG_STATUS_MASK) { + dev_err(&chip->cl->dev, + "cound not configure LED engine, status = 0x%.2x\n", + status); + ret = -1; + } + +out: + lp5523_stop_engine(chip); + return ret; +} + static int lp5523_update_program_memory(struct lp55xx_chip *chip, const u8 *data, size_t size) { |