/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2014 Siemens AG
 *
 * 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; version 2 of the License.
 *
 * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <console/console.h>
#include "baytrail/i2c.h"
#include "ptn3460.h"

/** \brief This functions sets up the DP2LVDS-converter to be used with the
 *         appropriate lcd panel
 * @param  lcd_type  Type of LCD we should set up the converter for
 * @param  *sib      Pointer to short info block structure
 * @param  *eib      Pointer to EDID info block structure
 * @return           0 on success or error code
 */
int ptn3460_init(char lcd_type, struct edidinfo *eib, struct shortinfo *sib)
{
	struct ptn_3460_config cfg;
	int status;


	status = i2c_init(PTN_I2C_CONTROLER);
	if (status)
		return (PTN_BUS_ERROR | status);

	/* If we are here, we have all the desired information for setting up */
	/* DP2LVDS converter. In addition, the information matches the connected */
	/* LCD-panel and therefore, we do not have to distinguish between */
	/* different panels here for the timing. Inside the converter, table 6 */
	/* will be used for the timings. */
	status = ptn3460_write_edid(6, eib->edid);
	if (status)
		return status;
	/* Select this table to be emulated */
	ptn_select_edid(6);
	/* Read PTN configuration data */
	status = i2c_read(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF,
			  (u8*)&cfg, PTN_CONFIG_LEN);
	if (status)
		return (PTN_BUS_ERROR | status);

	/* Set up configuration data according to the information blocks we get */
	cfg.dp_interface_ctrl = 0;
	cfg.lvds_interface_ctrl1 = 0x00;
	if (sib->panelFeatures[SIB_DISP_CON_IDX] == SIB_LVDS_DUAL_LANE)
		cfg.lvds_interface_ctrl1 |= 0x0b; /* Turn on dual LVDS lane and clock */
	if ((sib->panelFeatures[SIB_HWINIT_IDX] & 0x03) == SIB_COLOR_6BIT)
		cfg.lvds_interface_ctrl1 |= 0x20; /* Use 18 bits per pixel */

	cfg.lvds_interface_ctrl2 = 0x03;  /* no clock spreading, 300 mV LVDS swing */
	cfg.lvds_interface_ctrl3 = 0x00;  /* no LVDS signal swap */
	cfg.t2_delay = 1;		  /* Delay T2 (VDD to LVDS active) by 16 ms */
	cfg.t3_timing = 5;		  /* 250 ms from LVDS to backlight active */
	cfg.t12_timing = 20;		  /* 1 second re-power delay */
	cfg.t4_timing = 3;		  /* 150 ms backlight off to LVDS inactive */
	cfg.t5_delay = 1;		  /* Delay T5 (LVDS to VDD inactive) by 16 ms */
	cfg.backlight_ctrl = 0;		  /* Enable backlight control */

	/* Write back configuration data to PTN3460 */
	status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF,
			   (u8*)&cfg, PTN_CONFIG_LEN);
	if (status)
		return (PTN_BUS_ERROR | status);
	else
		return PTN_NO_ERROR;
}

/** \brief This functions reads one desired EDID data structure from PTN3460
 * @param  edid_num Number of EDID that must be read (0..6)
 * @param  *data    Pointer to a buffer where to store read data
 * @return          0 on success or error code
 */
int ptn3460_read_edid(u8 edid_num, u8 *data)
{
	int status;

	if (edid_num > PTN_MAX_EDID_NUM)
		return PTN_INVALID_EDID;
	/* First enable access to the desired EDID table */
	status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5,
			   &edid_num, 1);
	if (status)
		return (PTN_BUS_ERROR | status);

	/* Now we can simply read back EDID-data */
	status = i2c_read(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_EDID_OFF,
			  data, PTN_EDID_LEN);
	if (status)
		return (PTN_BUS_ERROR | status);
	else
		return PTN_NO_ERROR;
}

/** \brief This functions writes one EDID data structure to PTN3460
 * @param  edid_num  Number of EDID that must be written (0..6)
 * @param  *data     Pointer to a buffer where data to write is stored in
 * @return           0 on success or error code
 */
int ptn3460_write_edid(u8 edid_num, u8 *data)
{
	int status;

	if (edid_num > PTN_MAX_EDID_NUM)
		return PTN_INVALID_EDID;
	/* First enable access to the desired EDID table */
	status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5,
			   &edid_num, 1);
	if (status)
		return (PTN_BUS_ERROR | status);

	/* Now we can simply write EDID-data to ptn3460 */
	status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_EDID_OFF,
			   data, PTN_EDID_LEN);
	if (status)
		return (PTN_BUS_ERROR | status);
	else
		return PTN_NO_ERROR;
}

/** \brief  This functions selects one of 7 EDID-tables inside PTN3460
 *          which should be emulated on display port and turn emulation ON
 * @param   edid_num  Number of EDID to emulate (0..6)
 * @return            0 on success or error code
 */
int ptn_select_edid (u8 edid_num)
{
	int status;
	u8 val;

	if (edid_num > PTN_MAX_EDID_NUM)
		return PTN_INVALID_EDID;
	/* Enable emulation of the desired EDID table */
	val = (edid_num << 1) | 1;
	status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 4,
			   &val, 1);
	if (status)
		return (PTN_BUS_ERROR | status);
	else
		return PTN_NO_ERROR;
}

/** \brief This functions performs a flash operation which will write
 *         current configuration table (all the EDID-tables and the
 *         configuration space with a total amount of 1 KByte)
 *         to the internal flash of PTN3460
 * @param  none
 * @return 0 on success or error code
 */
int ptn3460_flash_config(void)
{
	int status;
	struct ptn_3460_flash flash;

	flash.cmd = 0x01;	/* perform erase and flash cycle */
	flash.magic = 0x7845;	/* Magic number to protect flash operation */
	flash.trigger = 0x56;	/* This value starts flash operation */
	status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_FLASH_CFG_OFF,
			   (u8*)&flash, PTN_FLASH_CFG_LEN);
	if (status) {
		return (PTN_BUS_ERROR | status);
	} else {
		/* To ensure the flash operation is finished, we have to wait 300 ms */
		mdelay(300);
		return PTN_NO_ERROR;
	}
}
