blob: 75380465d94bd8feb799a990d0d10361be05d5e6 [file] [log] [blame] [edit]
#include <linux/ctype.h>
#include <amlogic/leds-lp50xx.h>
#include <amlogic/leds-main.h>
static struct udevice *g_led_devp;
static enum LP50XX_INIT_STATUS led_init_ready;
#define CAL_FILE_LEN 2048
static int get_n_dot_data(const char *buffer,
const char *start_label, const char *end_label, char *data, size_t data_size)
{
const char *start = strstr(buffer, start_label);
const char *end = strstr(start, end_label);
int length;
if (!start || !end) {
pr_err("LED: cannot found n_dot data\n");
return -1;
}
length = end - start;
if (length >= data_size)
length = data_size - 1;
memcpy(data, start, length);
data[length] = '\0';
return 0;
}
static void parse_and_convert(const char *p, unsigned long settings_[], int len)
{
const char *ptr = p;
char num_str[16];
int i = 0;
int j = 0;
while (*ptr != '\0' && i < N_CAL_SETTINGS) {
memset(num_str, 0, sizeof(num_str));
j = 0;
while (*ptr != ',' && *ptr != ';' && *ptr != '\0')
num_str[j++] = *ptr++;
settings_[i++] = simple_strtoul(num_str, NULL, 10);
if (*ptr == ',' || *ptr == ';')
ptr++;
}
}
void lp50xx_get_cal_settings(unsigned int *settings, const char color_header[],
unsigned int led_index)
{
int i;
unsigned long settings_[N_CAL_SETTINGS];
const char *p;
char rgbw_buf[CAL_FILE_LEN];
char start_label[8];
char end_label[8];
const unsigned int max_chars = CAL_FILE_LEN;
char buf[max_chars];
if (get_cal_string(buf, max_chars))
return;
snprintf(start_label, sizeof(start_label), "%s%d", "n_dot_", led_index);
if (led_index < LP50XX_NUM_LEDS - 1)
snprintf(end_label, sizeof(end_label), "%s%d", "n_dot_", led_index + 1);
else
snprintf(end_label, sizeof(end_label), "%s%d", "status_", 0);
if (get_n_dot_data(buf, start_label, end_label, rgbw_buf, sizeof(rgbw_buf)))
return;
p = strstr(rgbw_buf, color_header);
if (!p) {
pr_err("LED: \"%s\" not found in cal file segment: %s\n",
color_header, buf);
return;
}
p += strlen(color_header);
parse_and_convert(p, settings_, sizeof(p));
for (i = 0; i < N_CAL_SETTINGS; ++i)
settings[i] = (unsigned int)settings_[i];
}
static void lp50xx_led_write_byte(struct udevice *led_devp, uint reg, int val)
{
dm_i2c_reg_write(led_devp, reg, val);
}
static void led_turn_off_write(struct udevice *led_devp, unsigned int led_index)
{
int i;
for (i = 0; i < 3; ++i)
lp50xx_led_write_byte(led_devp, LP50XX_COLOR_BASE + led_index * 3 + i, 0);
lp50xx_led_write_byte(led_devp, LP50XX_BRIGHTNESS_BASE + led_index, 0xff);
}
static void led_cal_setting_write(unsigned int *cal_settings,
struct udevice *led_devp, unsigned int led_index)
{
u8 brightness;
int i;
u8 rgb[3] = {0};
// color
for (i = 0; i < 3; ++i) {
rgb[i] = cal_settings[i];
lp50xx_led_write_byte(led_devp, LP50XX_COLOR_BASE + led_index * 3 + i, rgb[i]);
}
// brightness
brightness = cal_settings[3];
lp50xx_led_write_byte(led_devp, LP50XX_BRIGHTNESS_BASE + led_index, brightness);
}
static void turn_on_white_led(struct udevice *led_devp, unsigned int led_index)
{
unsigned int cal_settings[N_CAL_SETTINGS] = {0, 0, 0, 0};
char color_header[] = "White:";
lp50xx_get_cal_settings(cal_settings, color_header, led_index);
pr_info("LED: index(%d) show %s%d,%d,%d;%d\n", led_index, color_header,
cal_settings[0], cal_settings[1], cal_settings[2], cal_settings[3]);
led_cal_setting_write(cal_settings, led_devp, led_index);
}
static void turn_on_yellow_led(struct udevice *led_devp, unsigned int led_index)
{
unsigned int cal_settings[N_CAL_SETTINGS] = {0, 0, 0, 0};
char color_header[] = "NestYellow:";
lp50xx_get_cal_settings(cal_settings, color_header, led_index);
pr_info("LED: index(%d) show %s%d,%d,%d;%d\n", led_index, color_header,
cal_settings[0], cal_settings[1], cal_settings[2], cal_settings[3]);
led_cal_setting_write(cal_settings, led_devp, led_index);
}
static void turn_on_green_led(struct udevice *led_devp, unsigned int led_index)
{
unsigned int cal_settings[N_CAL_SETTINGS] = {0, 0, 0, 0};
char color_header[] = "NestGreen:";
lp50xx_get_cal_settings(cal_settings, color_header, led_index);
pr_info("LED: index(%d) show %s%d,%d,%d;%d\n", led_index, color_header,
cal_settings[0], cal_settings[1], cal_settings[2], cal_settings[3]);
led_cal_setting_write(cal_settings, led_devp, led_index);
}
static void turn_on_blue_led(struct udevice *led_devp, unsigned int led_index)
{
unsigned int cal_settings[N_CAL_SETTINGS] = {0, 0, 0, 0};
char color_header[] = "NestBlue:";
lp50xx_get_cal_settings(cal_settings, color_header, led_index);
pr_info("LED: index(%d) show %s%d,%d,%d;%d\n", led_index, color_header,
cal_settings[0], cal_settings[1], cal_settings[2], cal_settings[3]);
led_cal_setting_write(cal_settings, led_devp, led_index);
}
static void turn_on_orange_led(struct udevice *led_devp, unsigned int led_index)
{
unsigned int cal_settings[N_CAL_SETTINGS] = {0, 0, 0, 0};
char color_header[] = "NestOrange:";
lp50xx_get_cal_settings(cal_settings, color_header, led_index);
pr_info("LED: index(%d) show %s%d,%d,%d;%d\n", led_index, color_header,
cal_settings[0], cal_settings[1], cal_settings[2], cal_settings[3]);
led_cal_setting_write(cal_settings, led_devp, led_index);
}
static void turn_on_purple_led(struct udevice *led_devp, unsigned int led_index)
{
unsigned int cal_settings[N_CAL_SETTINGS] = {0, 0, 0, 0};
char color_header[] = "NestPurple:";
lp50xx_get_cal_settings(cal_settings, color_header, led_index);
pr_info("LED: index(%d) show %s%d,%d,%d;%d\n", led_index, color_header,
cal_settings[0], cal_settings[1], cal_settings[2], cal_settings[3]);
led_cal_setting_write(cal_settings, led_devp, led_index);
}
static void turn_on_pink_led(struct udevice *led_devp, unsigned int led_index)
{
unsigned int cal_settings[N_CAL_SETTINGS] = {0, 0, 0, 0};
char color_header[] = "NestPink:";
lp50xx_get_cal_settings(cal_settings, color_header, led_index);
pr_info("LED: index(%d) show %s%d,%d,%d;%d\n", led_index, color_header,
cal_settings[0], cal_settings[1], cal_settings[2], cal_settings[3]);
led_cal_setting_write(cal_settings, led_devp, led_index);
}
static void lp50xx_set_banks(struct udevice *led_devp)
{
int val = dm_i2c_reg_read(led_devp, LP50XX_DEVICE_CONFIG1);
if (!(val & LP50XX_Auto_Incr_EN)) {
val |= LP50XX_Auto_Incr_EN;
lp50xx_led_write_byte(led_devp, LP50XX_DEVICE_CONFIG1, val);
}
}
int lp50xx_sys_led_init(void)
{
int ret = 0;
struct udevice *led_devp = NULL;
int i;
if (led_init_ready)
return ret;
led_init_ready = INIT_DONE;
ret = i2c_get_chip_for_busnum(LP50XX_I2C_BUS_NUM, LP50XX_I2C_LED_REG, 1, &led_devp);
if (ret) {
pr_info("LED: i2c can't get bus 0x%x\n", LP50XX_I2C_LED_REG);
led_init_ready = INIT_NO_USED;
return ret;
}
// Enable driver
// Set Chip_EN
lp50xx_led_write_byte(led_devp, LP50XX_DEVICE_CONFIG0, 0x40);
// Set Log_Scale_EN = 0, Power_save_EN = 1, Auto_incr_EN = 1 and
// PWM_Dithering_EN = 1
lp50xx_led_write_byte(led_devp, LP50XX_DEVICE_CONFIG1, 0x1C);
// Set default brightness to 0xFF
for (i = 0; i < LP50XX_NUM_LEDS; ++i)
lp50xx_led_write_byte(led_devp, LP50XX_BRIGHTNESS_BASE + i, 0xFF);
lp50xx_set_banks(led_devp);
g_led_devp = led_devp;
return ret;
}
int lp50xx_turn_on_led(enum LED_ANIMATION led_animation, unsigned int led_index)
{
int ret;
struct udevice *led_devp;
if (check_read_cal_done() == -1)
return -1;
if (led_init_ready == INIT_NO_USED)
return -1;
if (led_init_ready != INIT_DONE) {
ret = lp50xx_sys_led_init();
if (ret)
return ret;
}
if (led_index >= LP50XX_NUM_LEDS) {
pr_err("LED: %s Can't to find led_index: %d\n",
__func__, led_index);
return -1;
}
led_devp = g_led_devp;
switch(led_animation) {
case WHITE:
turn_on_white_led(led_devp, led_index);
break;
case YELLOW:
turn_on_yellow_led(led_devp, led_index);
break;
case GREEN:
turn_on_green_led(led_devp, led_index);
break;
case BLUE:
turn_on_blue_led(led_devp, led_index);
break;
case ORANGE:
turn_on_orange_led(led_devp, led_index);
break;
case PURPLE:
turn_on_purple_led(led_devp, led_index);
break;
case PINK:
turn_on_pink_led(led_devp, led_index);
break;
default:
pr_err("LED: %s unknown led animation\n", __func__);
}
return 0;
}
int lp50xx_turn_off_led(unsigned int led_index)
{
int ret;
struct udevice *led_devp;
if (led_init_ready == INIT_NO_USED)
return -1;
if (led_init_ready != INIT_DONE) {
ret = lp50xx_sys_led_init();
if (ret)
return ret;
}
if (led_index >= LP50XX_NUM_LEDS) {
pr_err("LED: %s Can't to find led_index: %d\n",
__func__, led_index);
return -1;
}
led_devp = g_led_devp;
led_turn_off_write(led_devp, led_index);
return 0;
}
void lp50xx_uboot_init_led_status(void)
{
int i;
for (i = 0; i < LP50XX_NUM_LEDS; ++i)
lp50xx_turn_off_led(i);
// show group index is 2/3/6/7 led
const int indexs[] = {2, 3, 6, 7};
int length = sizeof(indexs) / sizeof(indexs[0]);
for (i = 0; i < length; ++i)
lp50xx_turn_on_led(WHITE, indexs[i]);
}
void lp50xx_start_kernel_led_status(void)
{
int i;
for (i = 0; i < LP50XX_NUM_LEDS; ++i)
lp50xx_turn_off_led(i);
// show all leds
for (i = 0; i < LP50XX_NUM_LEDS; ++i)
lp50xx_turn_on_led(WHITE, i);
}
void lp50xx_udisk_update_led_status(void)
{
int i;
// show 0/1/7 green led
for (i = 0; i < LP50XX_NUM_LEDS; ++i) {
if (i == 0 || i == 1 || i == 7)
lp50xx_turn_on_led(GREEN, i);
else
lp50xx_turn_off_led(i);
}
}