Change-Id: I202e5d285612b9bf237b588ea3c006187623fdc3 Signed-off-by: Elyes HAOUAS <ehaouas@noos.fr> Reviewed-on: https://review.coreboot.org/c/coreboot/+/44609 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Michael Niewöhner <foss@mniewoehner.de>
142 lines
3.9 KiB
C
142 lines
3.9 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
|
|
#include <console/console.h>
|
|
#include <device/i2c_bus.h>
|
|
#include <types.h>
|
|
|
|
#include "ptn3460.h"
|
|
|
|
/**
|
|
* \brief This function selects one of 7 EDID-tables inside PTN3460
|
|
* which should be emulated on display port and turn emulation ON
|
|
* @param *dev Pointer to the relevant I2C controller
|
|
* @param edid_num Number of EDID to emulate (0..6)
|
|
* @return PTN_SUCCESS or error code
|
|
*/
|
|
static int ptn_select_edid(struct device *dev, uint8_t edid_num)
|
|
{
|
|
int status = 0;
|
|
u8 val;
|
|
|
|
if (edid_num > PTN_MAX_EDID_NUM)
|
|
return PTN_INVALID_EDID;
|
|
val = (edid_num << 1) | PTN_ENABLE_EMULATION;
|
|
status = i2c_dev_writeb_at(dev, PTN_CONFIG_OFF + 4, val);
|
|
return status ? (PTN_BUS_ERROR | status) : PTN_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* \brief This function writes one EDID data structure to PTN3460
|
|
* @param *dev Pointer to the relevant I2C controller
|
|
* @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 PTN_SUCCESS on success or error code
|
|
*/
|
|
static int ptn3460_write_edid(struct device *dev, u8 edid_num, u8 *data)
|
|
{
|
|
int status;
|
|
int i;
|
|
|
|
if (edid_num > PTN_MAX_EDID_NUM)
|
|
return PTN_INVALID_EDID;
|
|
|
|
/* First enable access to the desired EDID table */
|
|
status = i2c_dev_writeb_at(dev, PTN_CONFIG_OFF + 5, edid_num);
|
|
if (status)
|
|
return (PTN_BUS_ERROR | status);
|
|
|
|
/* Now we can simply write EDID data to ptn3460 */
|
|
for (i = 0; i < PTN_EDID_LEN; i++) {
|
|
status = i2c_dev_writeb_at(dev, PTN_EDID_OFF + i, data[i]);
|
|
if (status)
|
|
return (PTN_BUS_ERROR | status);
|
|
}
|
|
return PTN_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* \brief This function sets up the DP2LVDS-converter to be used with the
|
|
* appropriate EDID data
|
|
* @param *dev Pointer to the I2C controller where PTN3460 is attached
|
|
*/
|
|
static void ptn3460_init(struct device *dev)
|
|
{
|
|
struct ptn_3460_config cfg;
|
|
uint8_t edid_data[PTN_EDID_LEN], edid_tab, *ptr = (uint8_t *) &cfg;
|
|
int i, val;
|
|
|
|
/* Mainboard provides EDID data. */
|
|
if (mb_get_edid(edid_data) != CB_SUCCESS) {
|
|
printk(BIOS_ERR, "PTN3460 error: Unable to get EDID data from mainboard.\n");
|
|
return;
|
|
}
|
|
|
|
/* Mainboard decides which EDID table has to be used. */
|
|
edid_tab = mb_select_edid_table();
|
|
if (edid_tab > PTN_MAX_EDID_NUM) {
|
|
printk(BIOS_ERR, "PTN3460 error: invalid EDID table (%d) selected.\n",
|
|
edid_tab);
|
|
return;
|
|
}
|
|
/* Write EDID data into PTN. */
|
|
val = ptn3460_write_edid(dev, edid_tab, edid_data);
|
|
if (val != PTN_SUCCESS) {
|
|
printk(BIOS_ERR, "PTN3460 error: writing EDID data into device failed.\n");
|
|
return;
|
|
}
|
|
/* Activate the selected EDID block. */
|
|
ptn_select_edid(dev, edid_tab);
|
|
/* Read out PTN configuration data. */
|
|
for (i = 0; i < sizeof(struct ptn_3460_config); i++) {
|
|
val = i2c_dev_readb_at(dev, PTN_CONFIG_OFF + i);
|
|
if (val < 0) {
|
|
printk(BIOS_ERR,
|
|
"PTN3460 error: Unable to read config data from device.\n");
|
|
return;
|
|
}
|
|
*ptr++ = (uint8_t)val; /* fill config structure via ptr */
|
|
}
|
|
/* Mainboard can modify the configuration data.
|
|
Write back configuration data to PTN3460 if modified by mainboard */
|
|
if (mb_adjust_cfg(&cfg) == PTN_CFG_MODIFIED) {
|
|
ptr = (uint8_t *) &cfg;
|
|
for (i = 0; i < sizeof(struct ptn_3460_config); i++) {
|
|
val = i2c_dev_writeb_at(dev, PTN_CONFIG_OFF + i, *ptr++);
|
|
if (val < 0) {
|
|
printk(BIOS_ERR,
|
|
"PTN3460 error: Unable to write config data.\n");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
__weak enum cb_err mb_get_edid(uint8_t edid_data[0x80])
|
|
{
|
|
return CB_ERR;
|
|
}
|
|
__weak uint8_t mb_select_edid_table(void)
|
|
{
|
|
return 0;
|
|
}
|
|
__weak int mb_adjust_cfg(struct ptn_3460_config *cfg_ptr)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static struct device_operations ptn3460_ops = {
|
|
.read_resources = noop_read_resources,
|
|
.set_resources = noop_set_resources,
|
|
.init = ptn3460_init,
|
|
};
|
|
|
|
static void ptn3460_enable(struct device *dev)
|
|
{
|
|
dev->ops = &ptn3460_ops;
|
|
}
|
|
|
|
struct chip_operations drivers_i2c_ptn3460_ops = {
|
|
CHIP_NAME("PTN3460")
|
|
.enable_dev = ptn3460_enable
|
|
};
|