/*
 * 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;
}

