blob: 347bc9ca37e45366e37df02e4cef6062302971be [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>
Werner Zehbf13d3f2016-04-25 12:24:17 +020017#include <hwilib.h>
Werner Zeh507c9c52016-11-23 07:49:52 +010018#include <string.h>
Ben Gardnerfa6014a2015-12-08 21:20:25 -060019#include "soc/i2c.h"
Werner Zehc42a6132015-02-12 12:40:15 +010020#include "ptn3460.h"
21
22/** \brief This functions sets up the DP2LVDS-converter to be used with the
23 * appropriate lcd panel
Werner Zehbf13d3f2016-04-25 12:24:17 +020024 * @param *hwi_block Filename in CBFS of the block to use as HW-Info
25 * @return 0 on success or error code
Werner Zehc42a6132015-02-12 12:40:15 +010026 */
Werner Zehbf13d3f2016-04-25 12:24:17 +020027int ptn3460_init(char *hwi_block)
Werner Zehc42a6132015-02-12 12:40:15 +010028{
29 struct ptn_3460_config cfg;
30 int status;
Werner Zehbf13d3f2016-04-25 12:24:17 +020031 uint8_t disp_con = 0, color_depth = 0;
32 uint8_t edid_data[0x80];
Werner Zeh507c9c52016-11-23 07:49:52 +010033 uint8_t hwid[4], tcu31_hwid[4] = {7, 9, 2, 0};
Werner Zehc42a6132015-02-12 12:40:15 +010034
Werner Zehbf13d3f2016-04-25 12:24:17 +020035 if (!hwi_block || hwilib_find_blocks(hwi_block) != CB_SUCCESS) {
36 printk(BIOS_ERR, "LCD: Info block \"%s\" not found!\n",
37 hwi_block);
38 return 1;
39 }
Werner Zehc42a6132015-02-12 12:40:15 +010040
41 status = i2c_init(PTN_I2C_CONTROLER);
42 if (status)
43 return (PTN_BUS_ERROR | status);
44
Werner Zehbf13d3f2016-04-25 12:24:17 +020045 /* Get all needed information from hwinfo block */
46 if (hwilib_get_field(Edid, edid_data, 0x80) != sizeof(edid_data)) {
47 printk(BIOS_ERR, "LCD: No EDID data available in %s\n",
48 hwi_block);
49 return 1;
50 }
51 if ((hwilib_get_field(PF_DisplCon, &disp_con, 1) != 1)) {
52 printk(BIOS_ERR, "LCD: Missing panel features from %s\n",
53 hwi_block);
54 return 1;
55 }
56 if (hwilib_get_field(PF_Color_Depth ,&color_depth, 1) != 1) {
57 printk(BIOS_ERR, "LCD: Missing panel features from %s\n",
58 hwi_block);
59 return 1;
60 }
61 /* Here, all the desired information for setting up DP2LVDS converter*/
62 /* are present. Inside the converter, table 6 will be used for */
63 /* the timings. */
64 if ((status = ptn3460_write_edid(6, edid_data)) != 0)
Werner Zehc42a6132015-02-12 12:40:15 +010065 return status;
66 /* Select this table to be emulated */
67 ptn_select_edid(6);
68 /* Read PTN configuration data */
69 status = i2c_read(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF,
70 (u8*)&cfg, PTN_CONFIG_LEN);
71 if (status)
72 return (PTN_BUS_ERROR | status);
73
Werner Zehbf13d3f2016-04-25 12:24:17 +020074 /* Set up configuration data according to the hwinfo blocks we get */
Werner Zehc42a6132015-02-12 12:40:15 +010075 cfg.dp_interface_ctrl = 0;
76 cfg.lvds_interface_ctrl1 = 0x00;
Werner Zehbf13d3f2016-04-25 12:24:17 +020077 if (disp_con == PF_DISPLCON_LVDS_DUAL)
Werner Zehc42a6132015-02-12 12:40:15 +010078 cfg.lvds_interface_ctrl1 |= 0x0b; /* Turn on dual LVDS lane and clock */
Werner Zehbf13d3f2016-04-25 12:24:17 +020079 if (color_depth == PF_COLOR_DEPTH_6BIT)
Werner Zehc42a6132015-02-12 12:40:15 +010080 cfg.lvds_interface_ctrl1 |= 0x20; /* Use 18 bits per pixel */
81
82 cfg.lvds_interface_ctrl2 = 0x03; /* no clock spreading, 300 mV LVDS swing */
Werner Zeh0575a4f2016-12-01 10:57:34 +010083 /* Swap LVDS even and odd lanes for HW-ID 7.9.2.0 only. */
84 if (hwilib_get_field(HWID, hwid, sizeof(hwid)) == sizeof(hwid) &&
85 !(memcmp(hwid, tcu31_hwid, sizeof(hwid)))) {
Werner Zeh507c9c52016-11-23 07:49:52 +010086 cfg.lvds_interface_ctrl3 = 0x01; /* swap LVDS even and odd */
Werner Zeh0575a4f2016-12-01 10:57:34 +010087 } else
88 cfg.lvds_interface_ctrl3 = 0x00; /* no LVDS signal swap */
Werner Zehc42a6132015-02-12 12:40:15 +010089 cfg.t2_delay = 1; /* Delay T2 (VDD to LVDS active) by 16 ms */
Werner Zeh77ba8822016-10-04 11:59:59 +020090 cfg.t3_timing = 10; /* 500 ms from LVDS to backlight active */
Werner Zehc42a6132015-02-12 12:40:15 +010091 cfg.t12_timing = 20; /* 1 second re-power delay */
92 cfg.t4_timing = 3; /* 150 ms backlight off to LVDS inactive */
93 cfg.t5_delay = 1; /* Delay T5 (LVDS to VDD inactive) by 16 ms */
94 cfg.backlight_ctrl = 0; /* Enable backlight control */
95
96 /* Write back configuration data to PTN3460 */
97 status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF,
98 (u8*)&cfg, PTN_CONFIG_LEN);
99 if (status)
100 return (PTN_BUS_ERROR | status);
101 else
102 return PTN_NO_ERROR;
103}
104
105/** \brief This functions reads one desired EDID data structure from PTN3460
106 * @param edid_num Number of EDID that must be read (0..6)
107 * @param *data Pointer to a buffer where to store read data
108 * @return 0 on success or error code
109 */
110int ptn3460_read_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 read back EDID-data */
123 status = i2c_read(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 writes one EDID data structure to PTN3460
132 * @param edid_num Number of EDID that must be written (0..6)
133 * @param *data Pointer to a buffer where data to write is stored in
134 * @return 0 on success or error code
135 */
136int ptn3460_write_edid(u8 edid_num, u8 *data)
137{
138 int status;
139
140 if (edid_num > PTN_MAX_EDID_NUM)
141 return PTN_INVALID_EDID;
142 /* First enable access to the desired EDID table */
143 status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5,
144 &edid_num, 1);
145 if (status)
146 return (PTN_BUS_ERROR | status);
147
148 /* Now we can simply write EDID-data to ptn3460 */
149 status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_EDID_OFF,
150 data, PTN_EDID_LEN);
151 if (status)
152 return (PTN_BUS_ERROR | status);
153 else
154 return PTN_NO_ERROR;
155}
156
157/** \brief This functions selects one of 7 EDID-tables inside PTN3460
158 * which should be emulated on display port and turn emulation ON
159 * @param edid_num Number of EDID to emulate (0..6)
160 * @return 0 on success or error code
161 */
162int ptn_select_edid (u8 edid_num)
163{
164 int status;
165 u8 val;
166
167 if (edid_num > PTN_MAX_EDID_NUM)
168 return PTN_INVALID_EDID;
169 /* Enable emulation of the desired EDID table */
170 val = (edid_num << 1) | 1;
171 status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 4,
172 &val, 1);
173 if (status)
174 return (PTN_BUS_ERROR | status);
175 else
176 return PTN_NO_ERROR;
177}
178
179/** \brief This functions performs a flash operation which will write
180 * current configuration table (all the EDID-tables and the
181 * configuration space with a total amount of 1 KByte)
182 * to the internal flash of PTN3460
183 * @param none
184 * @return 0 on success or error code
185 */
186int ptn3460_flash_config(void)
187{
188 int status;
189 struct ptn_3460_flash flash;
190
191 flash.cmd = 0x01; /* perform erase and flash cycle */
192 flash.magic = 0x7845; /* Magic number to protect flash operation */
193 flash.trigger = 0x56; /* This value starts flash operation */
194 status = i2c_write(PTN_I2C_CONTROLER, PTN_SLAVE_ADR, PTN_FLASH_CFG_OFF,
195 (u8*)&flash, PTN_FLASH_CFG_LEN);
196 if (status) {
197 return (PTN_BUS_ERROR | status);
198 } else {
199 /* To ensure the flash operation is finished, we have to wait 300 ms */
200 mdelay(300);
201 return PTN_NO_ERROR;
202 }
203}