blob: 76ac282052c1caab4b8d55e1fe952ee103cc3817 [file] [log] [blame]
/*
* drivers/amlogic/media/vout/lcd/bl_ldim/ldim_drv.c
*
* Copyright (C) 2015 Amlogic, Inc. All rights reserved.
*
* 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 License, or
* (at your option) 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <common.h>
#include <malloc.h>
#include <asm/arch/gpio.h>
#include <fdtdec.h>
#include <amlogic/media/vout/lcd/aml_lcd.h>
#include <amlogic/media/vout/lcd/bl_ldim.h>
#include "../lcd_reg.h"
#include "../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 struct ldim_config_s ldim_config = {
.row = 1,
.col = 1,
};
static int ldim_power_on(void)
{
if (ldim_driver.device_power_on)
ldim_driver.device_power_on();
else
LDIMERR("%s: device_power_on is null\n", __func__);
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();
else
LDIMERR("%s: device_power_off is null\n", __func__);
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;
ldim_level = level;
if (ldim_on_flag == 0)
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)
{
LDIMPR("%s:\n", __func__);
printf("valid_flag = %d\n"
"dev_index = %d\n"
"ldim_blk_row = %d\n"
"ldim_blk_col = %d\n"
"ldim_on_flag = %d\n",
ldim_driver.valid_flag,
ldim_driver.dev_index,
ldim_blk_row,
ldim_blk_col,
ldim_on_flag);
if (ldim_driver.device_config_print)
ldim_driver.device_config_print();
}
static struct aml_ldim_driver_s ldim_driver = {
.valid_flag = 0, /* default invalid, active when bl_ctrl_method=ldim */
.dev_index = 0,
.ldim_conf = &ldim_config,
.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_config_print = 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;
}
int ldim_config_load_from_dts(char *dt_addr, int child_offset)
{
char *propdata;
if (child_offset < 0) {
LDIMERR("not find backlight node %s\n", 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 = 1;
} else {
ldim_blk_row = be32_to_cpup((u32*)propdata);
ldim_blk_col = be32_to_cpup((((u32*)propdata)+1));
ldim_config.row = ldim_blk_row;
ldim_config.col = ldim_blk_col;
}
LDIMPR("get region row = %d, col = %d\n", ldim_blk_row, ldim_blk_col);
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 = 0xff;
} else {
ldim_driver.dev_index = be32_to_cpup((u32*)propdata);
}
LDIMPR("get dev_index = %d\n", ldim_driver.dev_index);
return 0;
}
int ldim_config_load_from_unifykey(unsigned char *para)
{
unsigned char *p;
if (para == NULL) {
LDIMERR("backlight unifykey buf is NULL\n");
return -1;
}
p = para;
/* ldim: 24byte */
/* get bl_ldim_region_row_col 4byte*/
ldim_blk_row = *(p + LCD_UKEY_BL_LDIM_ROW);
ldim_blk_col = *(p + LCD_UKEY_BL_LDIM_COL);
ldim_config.row = ldim_blk_row;
ldim_config.col = ldim_blk_col;
LDIMPR("get region row = %d, col = %d\n", ldim_blk_row, ldim_blk_col);
/* get ldim_dev_index 1byte*/
ldim_driver.dev_index = *(p + LCD_UKEY_BL_LDIM_DEV_INDEX);
LDIMPR("get dev_index = %d\n", ldim_driver.dev_index);
return 0;
}
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 */
case 2: /* unifykey */
if (dt_addr) {
if (lcd_debug_print_flag)
LDIMPR("load ldim_dev_config from dts\n");
ret = aml_ldim_device_probe(dt_addr);
}
break;
case 1: /* bsp */
LDIMPR("%s: not support bsp 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;
}