/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of The Linux Foundation, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <err.h>
#include <debug.h>
#include <spmi.h>
#include <qpnp_wled.h>
#include <qpnp_lcdb.h>
#include <qtimer.h>
#include <target.h>

struct qpnp_lcdb *lcdb;

int qpnp_lcdb_enable(bool state)
{
	if (!lcdb) {
		dprintf(CRITICAL, "%s: lcdb is not initialized yet\n", __func__);
		return ERROR;
	}

	pmic_spmi_reg_mask_write(lcdb->lcdb_base + QPNP_LCDB_ENABLE_CTL_REG,
		QPNP_LCDB_ENABLE_CTL_MASK, (state << LCDB_ENABLE_SHIFT));

	return 0;
}

static int qpnp_lcdb_set_voltage(struct qpnp_lcdb *lcdb)
{
	int rc = -1;
	uint32_t new_uV, boost_ref_volt;
	uint8_t val;

	/* Set LDO Voltage */
	if (lcdb->ldo_min_volt < lcdb->ldo_init_volt) {
		dprintf(CRITICAL, "qpnp_ldo_set_voltage failed, min_uV %d is "
			"less than the minimum supported voltage %d\n",
			lcdb->ldo_min_volt, lcdb->ldo_init_volt);
		return rc;
	}

	val = ((lcdb->ldo_min_volt - lcdb->ldo_init_volt) +
		LDO_VREG_STEP_SIZE_UV - 1) / LDO_VREG_STEP_SIZE_UV;
	new_uV = val * LDO_VREG_STEP_SIZE_UV + lcdb->ldo_init_volt;
	if (new_uV > lcdb->ldo_max_volt) {
		dprintf(CRITICAL, "qpnp_ldo_set_voltage unable to set voltage "
			"(%d %d)\n", lcdb->ldo_min_volt, lcdb->ldo_max_volt);
		return rc;
	}

	/* Value adjustment as initial 1V has 100mV step and rest 50mV step */
	if ( val > 18 )
		val = val - 9;
	else
		val = val / 2;

	pmic_spmi_reg_mask_write(lcdb->lcdb_base +
				QPNP_LCDB_LDO_OUTPUT_VOLTAGE_REG,
				QPNP_LCDB_LDO_OUTPUT_VOLTAGE_MASK, val);

	udelay(2);

	/* Set NCP voltage */
	if (lcdb->ncp_min_volt < lcdb->ncp_init_volt) {
		dprintf(CRITICAL, "qpnp_ncp_set_voltage failed, min_uV %d is "
			"less than the minimum supported voltage %d\n",
			lcdb->ncp_min_volt, lcdb->ncp_init_volt);
		return rc;
	}

	val = ((lcdb->ncp_min_volt - lcdb->ncp_init_volt) +
			NCP_VREG_STEP_SIZE_UV - 1) / NCP_VREG_STEP_SIZE_UV;
	new_uV = val * NCP_VREG_STEP_SIZE_UV + lcdb->ncp_init_volt;
	if (new_uV > lcdb->ncp_max_volt) {
		dprintf(CRITICAL, "qpnp_ncp_set_voltage unable to set voltage "
			"(%d %d)\n", lcdb->ncp_min_volt, lcdb->ncp_max_volt);
		return rc;
	}

	/* Value adjustment as initial 1V has 100mV step and rest 50mV step */
	if ( val > 18 )
		val = val - 9;
	else
		val = val / 2;

	pmic_spmi_reg_mask_write(lcdb->lcdb_base +
				QPNP_LCDB_NCP_OUTPUT_VOLTAGE_REG,
				QPNP_LCDB_NCP_OUTPUT_VOLTAGE_MASK, val);

	udelay(2);

	/* Set Boost voltage */
	boost_ref_volt = ((lcdb->ldo_max_volt > lcdb->ncp_max_volt) ?
			lcdb->ldo_max_volt : lcdb->ncp_max_volt) +
			LCDB_BOOST_HEADROOM_VOLT_UV;
	if (boost_ref_volt < lcdb->bst_init_volt)
		boost_ref_volt = lcdb->bst_init_volt;

	val = ((boost_ref_volt - lcdb->bst_init_volt) +
		BST_VREG_STEP_SIZE_UV - 1) / BST_VREG_STEP_SIZE_UV;
	new_uV = val * BST_VREG_STEP_SIZE_UV + lcdb->bst_init_volt;

	pmic_spmi_reg_mask_write(lcdb->lcdb_base +
				QPNP_LCDB_BST_OUTPUT_VOLTAGE_REG,
				QPNP_LCDB_BST_OUTPUT_VOLTAGE_MASK, val);

	return 0;
}

static int qpnp_lcdb_config(struct qpnp_lcdb *lcdb)
{
	int rc = 0;
	uint8_t reg = 0;

	/* TODO: Set power up & down delay register */
	if (lcdb->lcdb_pwrup_dly_ms > QPNP_LCDB_PWRUP_DLY_MAX_MS)
		lcdb->lcdb_pwrup_dly_ms = QPNP_LCDB_PWRUP_DLY_MAX_MS;

	if (lcdb->lcdb_pwrdn_dly_ms > QPNP_LCDB_PWRDN_DLY_MAX_MS)
		lcdb->lcdb_pwrdn_dly_ms = QPNP_LCDB_PWRDN_DLY_MAX_MS;

	reg = pmic_spmi_reg_read(lcdb->lcdb_base +
			QPNP_LCDB_PWRUP_PWRDN_CTL_REG);

	/* Set power up delay */
	reg &= QPNP_LCDB_PWRUP_DLY_MASK;
	reg |= (lcdb->lcdb_pwrup_dly_ms << LCDB_PWRUP_DLY_SHIFT);

	/* Set power down delay */
	reg &= QPNP_LCDB_PWRDN_DLY_MASK;
	reg |= (lcdb->lcdb_pwrdn_dly_ms);

	pmic_spmi_reg_write(lcdb->lcdb_base + QPNP_LCDB_PWRUP_PWRDN_CTL_REG,
			reg);

	/* Make LCDB module ready */
	pmic_spmi_reg_mask_write(lcdb->lcdb_base + QPNP_LCDB_MODULE_RDY_REG,
		QPNP_LCDB_MODULE_RDY_MASK, LCDB_MODULE_RDY);

	/* Set regulator voltage */
	rc = qpnp_lcdb_set_voltage(lcdb);

	return rc;
}

static int qpnp_lcdb_setup(struct qpnp_lcdb *lcdb,
			struct qpnp_wled_config_data *config)
{
	lcdb->lcdb_base = QPNP_LCDB_BASE;
	lcdb->lcdb_pwrup_dly_ms = config->pwr_up_delay;
	lcdb->lcdb_pwrdn_dly_ms = config->pwr_down_delay;
	lcdb->ldo_min_volt = config->lab_min_volt;
	lcdb->ldo_max_volt = config->lab_max_volt;
	lcdb->ldo_init_volt = LCDB_LDO_INIT_VOLTAGE_UV;
	lcdb->ncp_min_volt = config->ibb_min_volt;
	lcdb->ncp_max_volt = config->ibb_max_volt;
	lcdb->ncp_init_volt = LCDB_NCP_INIT_VOLTAGE_UV;
	lcdb->bst_init_volt = LCDB_BOOST_INIT_VOLTAGE_UV;

	return 0;
}

int qpnp_lcdb_init(struct qpnp_wled_config_data *config)
{
	int rc;

	if (!target_is_pmi_enabled())
		return ERR_NOT_FOUND;

	lcdb = malloc(sizeof(struct qpnp_lcdb));
	if (!lcdb)
		return ERR_NO_MEMORY;

	memset(lcdb, 0, sizeof(struct qpnp_lcdb));

	rc = qpnp_lcdb_setup(lcdb, config);
	if(rc) {
		dprintf(CRITICAL, "Setting LCDB parameters failed\n");
		return rc;
	}

	rc = qpnp_lcdb_config(lcdb);
	if (rc) {
		dprintf(CRITICAL, "lcdb config failed\n");
		return rc;
	}

	return rc;
}
