blob: 56d4c005a364b02a3e35463225c7c87639ce7969 [file] [log] [blame]
/*
* drivers/display/lcd/lcd_bl_ldim/ldim_drv.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the named License,
* or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <common.h>
#include <malloc.h>
#include <asm/arch/gpio.h>
#ifdef CONFIG_OF_LIBFDT
#include <libfdt.h>
#endif
#include <amlogic/aml_lcd.h>
#include <amlogic/aml_ldim.h>
#include "../aml_lcd_reg.h"
#include "../aml_lcd_common.h"
#include "ldim_drv.h"
#define LD_DATA_MIN 10
#define LDIM_BRI_LEVEL_MAX 0xfff
#define LDIM_BRI_LEVEL_MIN 0x7f
static unsigned int ldim_blk_row = 1;
static unsigned int ldim_blk_col = 8;
static struct aml_ldim_driver_s ldim_driver;
static int ldim_on_flag;
static int ldim_level;
static int ldim_set_level(unsigned int level);
static int ldim_power_on(void)
{
if (ldim_driver.device_power_on) {
ldim_driver.device_power_on();
ldim_on_flag = 1;
}
if (ldim_level > 0)
ldim_set_level(ldim_level);
return 0;
}
static int ldim_power_off(void)
{
ldim_on_flag = 0;
if (ldim_driver.device_power_off)
ldim_driver.device_power_off();
return 0;
}
static void ldim_brightness_update(unsigned int level)
{
unsigned int size;
unsigned int i;
size = ldim_blk_row * ldim_blk_col;
for (i = 0; i < size; i++)
ldim_driver.ldim_matrix_buf[i] = (unsigned short)level;
if (ldim_driver.device_bri_update)
ldim_driver.device_bri_update(ldim_driver.ldim_matrix_buf, size);
else
LDIMPR("%s: device_bri_update is null\n", __func__);
}
static int ldim_set_level(unsigned int level)
{
int ret = 0;
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
unsigned int level_max, level_min;
if (ldim_on_flag == 0) {
ldim_level = level;
return 0;
}
level_max = lcd_drv->bl_config->level_max;
level_min = lcd_drv->bl_config->level_min;
level = ((level - level_min) * (LD_DATA_MAX - LD_DATA_MIN)) /
(level_max - level_min) + LD_DATA_MIN;
level &= 0xfff;
ldim_brightness_update(level);
return ret;
}
static void ldim_config_print(void)
{
struct bl_pwm_config_s *ld_pwm;
LDIMPR("%s:\n", __func__);
printf("valid_flag = %d\n"
"dev_index = %d\n"
"ldim_on_flag = %d\n",
ldim_driver.valid_flag,
ldim_driver.dev_index,
ldim_on_flag);
if (ldim_driver.ldev_conf) {
ld_pwm = &ldim_driver.ldev_conf->pwm_config;
printf("dev_name = %s\n"
"cs_hold_delay = %d\n"
"cs_clk_delay = %d\n"
"en_gpio = %d\n"
"en_gpio_on = %d\n"
"en_gpio_off = %d\n"
"write_check = %d\n"
"dim_min = 0x%03x\n"
"dim_max = 0x%03x\n"
"cmd_size = %d\n",
ldim_driver.ldev_conf->name,
ldim_driver.ldev_conf->cs_hold_delay,
ldim_driver.ldev_conf->cs_clk_delay,
ldim_driver.ldev_conf->en_gpio,
ldim_driver.ldev_conf->en_gpio_on,
ldim_driver.ldev_conf->en_gpio_off,
ldim_driver.ldev_conf->write_check,
ldim_driver.ldev_conf->dim_min,
ldim_driver.ldev_conf->dim_max,
ldim_driver.ldev_conf->cmd_size);
if (ld_pwm->pwm_port < BL_PWM_MAX) {
printf("pwm_port = %d\n"
"pwm_pol = %d\n"
"pwm_freq = %d\n"
"pwm_duty = %d%%\n"
"pinmux_flag = %d\n",
ld_pwm->pwm_port, ld_pwm->pwm_method,
ld_pwm->pwm_freq, ld_pwm->pwm_duty,
ld_pwm->pinmux_flag);
}
} else {
printf("device config is null\n");
}
}
static struct aml_ldim_driver_s ldim_driver = {
.valid_flag = 0, /* default invalid, active when bl_ctrl_method=ldim */
.dev_index = 0,
.ldev_conf = NULL,
.ldim_matrix_buf = NULL,
.power_on = ldim_power_on,
.power_off = ldim_power_off,
.set_level = ldim_set_level,
.config_print = ldim_config_print,
.pinmux_ctrl = NULL,
.device_power_on = NULL,
.device_power_off = NULL,
.device_bri_update = NULL,
};
struct aml_ldim_driver_s *aml_ldim_get_driver(void)
{
return &ldim_driver;
}
#ifdef CONFIG_OF_LIBFDT
static int ldim_config_load_from_dts(char *dt_addr)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
int parent_offset;
char *propdata;
char propname[30];
int child_offset;
unsigned int index;
parent_offset = fdt_path_offset(dt_addr, "/backlight");
if (parent_offset < 0) {
LDIMERR("not find /backlight node %s\n", fdt_strerror(parent_offset));
return -1;
}
index = lcd_drv->lcd_config->backlight_index;
sprintf(propname,"/backlight/backlight_%d", index);
child_offset = fdt_path_offset(dt_addr, propname);
if (child_offset < 0) {
LDIMERR("not find %s node %s\n", propname, fdt_strerror(child_offset));
return -1;
}
propdata = (char *)fdt_getprop(dt_addr, child_offset, "bl_ldim_region_row_col", NULL);
if (propdata == NULL) {
LDIMERR("failed to get bl_ldim_region_row_col\n");
ldim_blk_row = 1;
ldim_blk_col = 8;
} else {
ldim_blk_row = be32_to_cpup((u32*)propdata);
ldim_blk_col = be32_to_cpup((((u32*)propdata)+1));
}
propdata = (char *)fdt_getprop(dt_addr, child_offset, "ldim_dev_index", NULL);
if (propdata == NULL) {
LDIMERR("failed to get ldim_dev_index\n");
ldim_driver.dev_index = 0;
} else {
ldim_driver.dev_index = be32_to_cpup((u32*)propdata);
}
return 0;
}
#endif
int aml_ldim_probe(char *dt_addr, int flag)
{
unsigned int size;
int ret = -1;
ldim_on_flag = 0;
ldim_level = 0;
switch (flag) {
case 0: /* dts */
#ifdef CONFIG_OF_LIBFDT
if (dt_addr) {
if (lcd_debug_print_flag)
LDIMPR("load ldim_config from dts\n");
ldim_config_load_from_dts(dt_addr);
ret = aml_ldim_device_probe(dt_addr);
}
#endif
break;
case 1: /* bsp */
LDIMPR("%s: not support bsp config\n", __func__);
break;
case 2: /* unifykey */
LDIMPR("%s: not support unifykey config\n", __func__);
break;
default:
break;
}
if (ret) {
LDIMERR("%s failed\n", __func__);
return ret;
}
size = ldim_blk_row * ldim_blk_col;
ldim_driver.ldim_matrix_buf = (unsigned short *)malloc(sizeof(unsigned short) * size);
if (ldim_driver.ldim_matrix_buf == NULL) {
LDIMERR("ldim_matrix_buf malloc error\n");
return -1;
}
ldim_driver.valid_flag = 1;
LDIMPR("%s is ok\n", __func__);
return ret;
}