summaryrefslogtreecommitdiffstats
path: root/drivers/leds/leds-lp5523.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/leds/leds-lp5523.c')
-rw-r--r--drivers/leds/leds-lp5523.c70
1 files changed, 69 insertions, 1 deletions
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index b50948060a02..29c8b19a445e 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)
{