blob: a6fabf4ca3a3fc675bd0074e3f825153e0a4ff41 [file] [log] [blame]
#include <amlogic/aml_led.h>
#define LED_DEFAULT_PWM_FREQ 100000
#define FIN_FREQ (24 * 1000)
#define DUTY_MAX 1024
static struct aml_led pwm_led;
static unsigned int ledmode = -1;
static int pwm_calc(int duty, unsigned int pwm_freq, unsigned int *setting)
{
unsigned int div;
unsigned int pwm_cnt;
unsigned int pwm_lo, pwm_hi;
if (duty < 0)
duty = 0;
else if (duty > DUTY_MAX)
duty = DUTY_MAX;
for (div = 0; div < 0x7f; div++) {
pwm_cnt = FIN_FREQ * 1000 / (pwm_freq * (div + 1)) - 2;
if (pwm_cnt <= 0xffff)
break;
}
if (duty == 0) {
pwm_hi = 0;
pwm_lo = pwm_cnt;
}
else if (duty == DUTY_MAX) {
pwm_hi = pwm_cnt;
pwm_lo = 0;
}
else {
pwm_hi = pwm_cnt * duty;
pwm_hi /= DUTY_MAX;
pwm_lo = pwm_cnt - pwm_hi;
}
setting[0] = div;
setting[1] = pwm_lo;
setting[2] = pwm_hi;
return 0;
}
/*
static void pled_gpio_ctrl(int on)
{
unsigned int value;
value = readl(AO_RTI_PIN_MUX_REG);
value &= ~(3<<19);
writel(value, AO_RTI_PIN_MUX_REG);
value = readl(AO_GPIO_O_EN_N);
value &= ~((1<<11)|(1<<27));
#ifdef CONFIG_LED_PWM_INVERT
on = !on;
#endif
value |= (on<<27);
//printf("on=%d, value=0x%x\n", on, value);
writel(value, AO_GPIO_O_EN_N);
}
*/
static void pled_mux_to_pwm(void)
{
unsigned int value;
// GPIOAO_11 mux as PWM_AO_A
value = readl(AO_RTI_PIN_MUX_REG);
value |= (1<<19);
value &= ~(1<<20);
writel(value, AO_RTI_PIN_MUX_REG);
}
static void pled_set_brightness(int brightness)
{
unsigned int value;
unsigned int setting[3] = {0};
#ifdef CONFIG_LED_PWM_INVERT
brightness = DUTY_MAX - brightness;
#endif
pwm_calc(brightness, LED_DEFAULT_PWM_FREQ, &setting[0]);
value = readl(AO_PWM_MISC_REG_AB);
// clk div
value &= ~(0x7f<<8);
value |= (setting[0]<<8);
//clk enable
value |= 1<<15;
writel(value, AO_PWM_MISC_REG_AB);
// duty cycle
writel((setting[2] << 16) | setting[1], AO_PWM_PWM_A);
// enable PWM_AO_A
value = readl(AO_PWM_MISC_REG_AB);
value |= 0x3;
writel(value, AO_PWM_MISC_REG_AB);
}
static struct coord breath_inflections[]= {
{0, 0},
{1000, 80},
{2000, 256},
{2500, 512},
{3000, 1024},
{3200, 1024},
{4200, 512},
{5200, 256},
{7200, 80},
{9200, 0},
{9400, 0},
};
struct aml_led_config pled_config = {
.off_brightness = 0,
.on_brightness = DUTY_MAX,
.flash_off_brightness = 0,
.flash_off_time = 350,
.flash_on_brightness = DUTY_MAX,
.flash_on_time = 400,
.breath_inflections = breath_inflections,
.breath_inflections_num = 11,
.set_brightness = pled_set_brightness,
};
/*
* for suspend
*/
void pled_suspend_init(void)
{
if (ledmode == -1)
return;
pled_mux_to_pwm();
aml_led_init(&pwm_led, &pled_config);
//if (lwm_get_suspend(ledmode) == SHUTDOWN_MODE)
aml_led_event(&pwm_led, LED_EVENT_FLASH, 3);
if (lwm_get_standby(ledmode) == LWM_ON)
aml_led_event(&pwm_led, LED_EVENT_ON, 0);
else if(lwm_get_standby(ledmode) == LWM_FLASH)
aml_led_event(&pwm_led, LED_EVENT_FLASH, 0);
else if(lwm_get_standby(ledmode) == LWM_BREATH)
aml_led_event(&pwm_led, LED_EVENT_BREATH, 0);
else
aml_led_event(&pwm_led, LED_EVENT_OFF, 0);
}
void pled_suspend_timer_proc(void)
{
if (ledmode == -1)
return;
aml_led_timer_proc(&pwm_led);
}
/*
* for scp
*/
static void pled_scp_init(int mode)
{
ledmode = mode;
pled_mux_to_pwm();
}
static void pled_scp_timer_proc(int count)
{
int mod = 2;
if (lwm_get_suspend(ledmode) == RECOVERY_MODE)
mod = 3;
if (count%mod)
pled_set_brightness(pled_config.flash_on_brightness);
else
pled_set_brightness(pled_config.flash_off_brightness);
}
struct scp_led pwm_scp_led = {
.count = 0,
.init = pled_scp_init,
.timer_proc = pled_scp_timer_proc,
};