blob: ef25745ed150ddf3fb4ee3e9a6afb2ac5f5b506c [file] [log] [blame]
Uwe Poeche11a34ec2019-10-28 11:28:50 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2019 Siemens AG
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16
17#include <console/console.h>
18#include <device/i2c_bus.h>
19#include <types.h>
20
21#include "ptn3460.h"
22
23/**
24 * \brief This function selects one of 7 EDID-tables inside PTN3460
25 * which should be emulated on display port and turn emulation ON
26 * @param *dev Pointer to the relevant I2C controller
27 * @param edid_num Number of EDID to emulate (0..6)
28 * @return PTN_SUCCESS or error code
29 */
30static int ptn_select_edid(struct device *dev, uint8_t edid_num)
31{
32 int status = 0;
33 u8 val;
34
35 if (edid_num > PTN_MAX_EDID_NUM)
36 return PTN_INVALID_EDID;
37 val = (edid_num << 1) | PTN_ENABLE_EMULATION;
38 status = i2c_dev_writeb_at(dev, PTN_CONFIG_OFF + 4, val);
39 return status ? (PTN_BUS_ERROR | status) : PTN_SUCCESS;
40}
41
42/**
43 * \brief This function writes one EDID data structure to PTN3460
44 * @param *dev Pointer to the relevant I2C controller
45 * @param edid_num Number of EDID that must be written (0..6)
46 * @param *data Pointer to a buffer where data to write is stored in
47 * @return PTN_SUCCESS on success or error code
48 */
49static int ptn3460_write_edid(struct device *dev, u8 edid_num, u8 *data)
50{
51 int status;
52 int i;
53
54 if (edid_num > PTN_MAX_EDID_NUM)
55 return PTN_INVALID_EDID;
56
57 /* First enable access to the desired EDID table */
58 status = i2c_dev_writeb_at(dev, PTN_CONFIG_OFF + 5, edid_num);
59 if (status)
60 return (PTN_BUS_ERROR | status);
61
62 /* Now we can simply write EDID data to ptn3460 */
63 for (i = 0; i < PTN_EDID_LEN; i++) {
64 status = i2c_dev_writeb_at(dev, PTN_EDID_OFF + i, data[i]);
65 if (status)
66 return (PTN_BUS_ERROR | status);
67 }
68 return PTN_SUCCESS;
69}
70
71/**
72 * \brief This function sets up the DP2LVDS-converter to be used with the
73 * appropriate EDID data
74 * @param *dev Pointer to the I2C controller where PTN3460 is attached
75 */
76static void ptn3460_init(struct device *dev)
77{
78 struct ptn_3460_config cfg;
79 uint8_t edid_data[PTN_EDID_LEN], edid_tab, *ptr = (uint8_t *) &cfg;
80 int i, val;
81
82 /* Mainboard provides EDID data. */
83 if (mb_get_edid(edid_data) != CB_SUCCESS) {
84 printk(BIOS_ERR, "PTN3460 error: Unable to get EDID data from mainboard.\n");
85 return;
86 }
87
88 /* Mainboard decides which EDID table has to be used. */
89 edid_tab = mb_select_edid_table();
90 if (edid_tab > PTN_MAX_EDID_NUM) {
91 printk(BIOS_ERR, "PTN3460 error: invalid EDID table (%d) selected.\n",
92 edid_tab);
93 return;
94 }
95 /* Write EDID data into PTN. */
96 val = ptn3460_write_edid(dev, edid_tab, edid_data);
97 if (val != PTN_SUCCESS) {
98 printk(BIOS_ERR, "PTN3460 error: writing EDID data into device failed.\n");
99 return;
100 }
101 /* Activate the selected EDID block. */
102 ptn_select_edid(dev, edid_tab);
103 /* Read out PTN configuration data. */
104 for (i = 0; i < sizeof(struct ptn_3460_config); i++) {
105 val = i2c_dev_readb_at(dev, PTN_CONFIG_OFF + i);
106 if (val < 0) {
107 printk(BIOS_ERR,
108 "PTN3460 error: Unable to read config data from device.\n");
109 return;
110 }
111 *ptr++ = (uint8_t)val; /* fill config structure via ptr */
112 }
113 /* Mainboard can modify the configuration data.
114 Write back configuration data to PTN3460 if modified by mainboard */
115 if (mb_adjust_cfg(&cfg) == PTN_CFG_MODIFIED) {
116 ptr = (uint8_t *) &cfg;
117 for (i = 0; i < sizeof(struct ptn_3460_config); i++) {
118 val = i2c_dev_writeb_at(dev, PTN_CONFIG_OFF + i, *ptr++);
119 if (val < 0) {
120 printk(BIOS_ERR,
121 "PTN3460 error: Unable to write config data.\n");
122 return;
123 }
124 }
125 }
126}
127
128__weak enum cb_err mb_get_edid(uint8_t edid_data[0x80])
129{
130 return CB_ERR;
131}
132__weak uint8_t mb_select_edid_table(void)
133{
134 return 0;
135}
136__weak int mb_adjust_cfg(struct ptn_3460_config *cfg_ptr)
137{
138 return 0;
139}
140
141static struct device_operations ptn3460_ops = {
142 .read_resources = DEVICE_NOOP,
143 .set_resources = DEVICE_NOOP,
144 .enable_resources = DEVICE_NOOP,
145 .init = ptn3460_init,
146 .final = DEVICE_NOOP
147};
148
149static void ptn3460_enable(struct device *dev)
150{
151 dev->ops = &ptn3460_ops;
152}
153
154struct chip_operations drivers_i2c_ptn3460_ops = {
155 CHIP_NAME("PTN3460")
156 .enable_dev = ptn3460_enable
157};