blob: e371e53c7f7d61e05ac1c7a42179dd8ab7b41a66 [file] [log] [blame]
Werner Zehc42a6132015-02-12 12:40:15 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2014 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.
Werner Zehc42a6132015-02-12 12:40:15 +010014 */
15
16#include <console/console.h>
Ben Gardnerfa6014a2015-12-08 21:20:25 -060017#include "soc/i2c.h"
Werner Zehc42a6132015-02-12 12:40:15 +010018#include "ptn3460.h"
19
20/** \brief This functions sets up the DP2LVDS-converter to be used with the
21 * appropriate lcd panel
22 * @param lcd_type Type of LCD we should set up the converter for
23 * @param *sib Pointer to short info block structure
24 * @param *eib Pointer to EDID info block structure
25 * @return 0 on success or error code
26 */
27int ptn3460_init(char lcd_type, struct edidinfo *eib, struct shortinfo *sib)
28{
29 struct ptn_3460_config cfg;
30 int status;
31
32
33 status = i2c_init(PTN_I2C_CONTROLER);
34 if (status)
35 return (PTN_BUS_ERROR | status);
36
37 /* If we are here, we have all the desired information for setting up */
38 /* DP2LVDS converter. In addition, the information matches the connected */
39 /* LCD-panel and therefore, we do not have to distinguish between */
40 /* different panels here for the timing. Inside the converter, table 6 */
41 /* will be used for the timings. */
42 status = ptn3460_write_edid(6, eib->edid);
43 if (status)
44 return status;
45 /* Select this table to be emulated */
46 ptn_select_edid(6);
47 /* Read PTN configuration data */
48 status = i2c_read(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF,
49 (u8*)&cfg, PTN_CONFIG_LEN);
50 if (status)
51 return (PTN_BUS_ERROR | status);
52
53 /* Set up configuration data according to the information blocks we get */
54 cfg.dp_interface_ctrl = 0;
55 cfg.lvds_interface_ctrl1 = 0x00;
56 if (sib->panelFeatures[SIB_DISP_CON_IDX] == SIB_LVDS_DUAL_LANE)
57 cfg.lvds_interface_ctrl1 |= 0x0b; /* Turn on dual LVDS lane and clock */
58 if ((sib->panelFeatures[SIB_HWINIT_IDX] & 0x03) == SIB_COLOR_6BIT)
59 cfg.lvds_interface_ctrl1 |= 0x20; /* Use 18 bits per pixel */
60
61 cfg.lvds_interface_ctrl2 = 0x03; /* no clock spreading, 300 mV LVDS swing */
62 cfg.lvds_interface_ctrl3 = 0x00; /* no LVDS signal swap */
63 cfg.t2_delay = 1; /* Delay T2 (VDD to LVDS active) by 16 ms */
64 cfg.t3_timing = 5; /* 250 ms from LVDS to backlight active */
65 cfg.t12_timing = 20; /* 1 second re-power delay */
66 cfg.t4_timing = 3; /* 150 ms backlight off to LVDS inactive */
67 cfg.t5_delay = 1; /* Delay T5 (LVDS to VDD inactive) by 16 ms */
68 cfg.backlight_ctrl = 0; /* Enable backlight control */
69
70 /* Write back configuration data to PTN3460 */
71 status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF,
72 (u8*)&cfg, PTN_CONFIG_LEN);
73 if (status)
74 return (PTN_BUS_ERROR | status);
75 else
76 return PTN_NO_ERROR;
77}
78
79/** \brief This functions reads one desired EDID data structure from PTN3460
80 * @param edid_num Number of EDID that must be read (0..6)
81 * @param *data Pointer to a buffer where to store read data
82 * @return 0 on success or error code
83 */
84int ptn3460_read_edid(u8 edid_num, u8 *data)
85{
86 int status;
87
88 if (edid_num > PTN_MAX_EDID_NUM)
89 return PTN_INVALID_EDID;
90 /* First enable access to the desired EDID table */
91 status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5,
92 &edid_num, 1);
93 if (status)
94 return (PTN_BUS_ERROR | status);
95
96 /* Now we can simply read back EDID-data */
97 status = i2c_read(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_EDID_OFF,
98 data, PTN_EDID_LEN);
99 if (status)
100 return (PTN_BUS_ERROR | status);
101 else
102 return PTN_NO_ERROR;
103}
104
105/** \brief This functions writes one EDID data structure to PTN3460
106 * @param edid_num Number of EDID that must be written (0..6)
107 * @param *data Pointer to a buffer where data to write is stored in
108 * @return 0 on success or error code
109 */
110int ptn3460_write_edid(u8 edid_num, u8 *data)
111{
112 int status;
113
114 if (edid_num > PTN_MAX_EDID_NUM)
115 return PTN_INVALID_EDID;
116 /* First enable access to the desired EDID table */
117 status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5,
118 &edid_num, 1);
119 if (status)
120 return (PTN_BUS_ERROR | status);
121
122 /* Now we can simply write EDID-data to ptn3460 */
123 status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_EDID_OFF,
124 data, PTN_EDID_LEN);
125 if (status)
126 return (PTN_BUS_ERROR | status);
127 else
128 return PTN_NO_ERROR;
129}
130
131/** \brief This functions selects one of 7 EDID-tables inside PTN3460
132 * which should be emulated on display port and turn emulation ON
133 * @param edid_num Number of EDID to emulate (0..6)
134 * @return 0 on success or error code
135 */
136int ptn_select_edid (u8 edid_num)
137{
138 int status;
139 u8 val;
140
141 if (edid_num > PTN_MAX_EDID_NUM)
142 return PTN_INVALID_EDID;
143 /* Enable emulation of the desired EDID table */
144 val = (edid_num << 1) | 1;
145 status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 4,
146 &val, 1);
147 if (status)
148 return (PTN_BUS_ERROR | status);
149 else
150 return PTN_NO_ERROR;
151}
152
153/** \brief This functions performs a flash operation which will write
154 * current configuration table (all the EDID-tables and the
155 * configuration space with a total amount of 1 KByte)
156 * to the internal flash of PTN3460
157 * @param none
158 * @return 0 on success or error code
159 */
160int ptn3460_flash_config(void)
161{
162 int status;
163 struct ptn_3460_flash flash;
164
165 flash.cmd = 0x01; /* perform erase and flash cycle */
166 flash.magic = 0x7845; /* Magic number to protect flash operation */
167 flash.trigger = 0x56; /* This value starts flash operation */
168 status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_FLASH_CFG_OFF,
169 (u8*)&flash, PTN_FLASH_CFG_LEN);
170 if (status) {
171 return (PTN_BUS_ERROR | status);
172 } else {
173 /* To ensure the flash operation is finished, we have to wait 300 ms */
174 mdelay(300);
175 return PTN_NO_ERROR;
176 }
177}