blob: 35e338dc964439b73af567af7483b753be9e5afd [file] [log] [blame]
Shunqian Zhengd1cec752016-05-04 16:21:36 +08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2016 Rockchip Inc.
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#include <arch/cache.h>
17#include <arch/mmu.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020018#include <device/mmio.h>
Shunqian Zhengd1cec752016-05-04 16:21:36 +080019#include <console/console.h>
20#include <device/device.h>
21#include <delay.h>
22#include <edid.h>
23#include <gpio.h>
24#include <stdlib.h>
25#include <stddef.h>
26#include <string.h>
27#include <soc/addressmap.h>
28#include <soc/clock.h>
29#include <soc/display.h>
30#include <soc/edp.h>
31#include <soc/gpio.h>
32#include <soc/grf.h>
33#include <soc/mmu_operations.h>
Nickey Yangfe122d42017-04-27 09:38:06 +080034#include <soc/mipi.h>
Shunqian Zhengd1cec752016-05-04 16:21:36 +080035#include <soc/soc.h>
36#include <soc/vop.h>
37
38#include "chip.h"
39
Martin Rothe4b9af12016-11-29 10:50:52 -070040static void reset_edp(void)
41{
42 /* rst edp */
43 write32(&cru_ptr->softrst_con[17],
44 RK_SETBITS(1 << 12 | 1 << 13));
45 udelay(1);
46 write32(&cru_ptr->softrst_con[17],
47 RK_CLRBITS(1 << 12 | 1 << 13));
Ege Mihmanlibb9bdeb2018-01-07 18:03:07 -080048 printk(BIOS_WARNING, "Retrying EDP initialization.\n");
Martin Rothe4b9af12016-11-29 10:50:52 -070049}
50
Elyes HAOUASf3ca88b2018-05-25 09:52:45 +020051void rk_display_init(struct device *dev)
Shunqian Zhengd1cec752016-05-04 16:21:36 +080052{
53 struct edid edid;
Shunqian Zhengd1cec752016-05-04 16:21:36 +080054 struct soc_rockchip_rk3399_config *conf = dev->chip_info;
Shunqian Zhengd1cec752016-05-04 16:21:36 +080055 enum vop_modes detected_mode = VOP_MODE_UNKNOWN;
Lin Huang25fb09b2017-11-22 09:40:50 +080056 const struct mipi_panel_data *panel_data = NULL;
Ege Mihmanlibb9bdeb2018-01-07 18:03:07 -080057 int retry_count_init = 0;
58 int retry_count_edp_prepare = 0;
Shunqian Zhengd1cec752016-05-04 16:21:36 +080059
Lin Huang152e6752016-10-20 14:22:11 -070060 /* let's use vop0 in rk3399 */
61 uint32_t vop_id = 0;
Shunqian Zhengd1cec752016-05-04 16:21:36 +080062
63 switch (conf->vop_mode) {
64 case VOP_MODE_NONE:
65 return;
Shunqian Zhengd1cec752016-05-04 16:21:36 +080066 case VOP_MODE_EDP:
67 printk(BIOS_DEBUG, "Attempting to set up EDP display.\n");
Julius Werner8e42bd1c2016-11-01 15:24:54 -070068 rkclk_configure_vop_aclk(vop_id, 200 * MHz);
Lin Huang4ecccff2017-01-18 09:44:34 +080069 rkclk_configure_edp(25 * MHz);
Shunqian Zhengd1cec752016-05-04 16:21:36 +080070
Lin Huang152e6752016-10-20 14:22:11 -070071 /* select edp signal from vop0 */
72 write32(&rk3399_grf->soc_con20, RK_CLRBITS(1 << 5));
Shunqian Zhengd1cec752016-05-04 16:21:36 +080073
74 /* select edp clk from SoC internal 24M crystal, otherwise,
75 * it will source from edp's 24M clock (that depends on
76 * edp vendor, could be unstable)
77 */
78 write32(&rk3399_grf->soc_con25, RK_SETBITS(1 << 11));
79
Lin Huang079b5c62016-11-21 17:35:20 +080080retry_edp:
Ege Mihmanlibb9bdeb2018-01-07 18:03:07 -080081 /* Reset in case code jumped here. */
82 retry_count_init = 0;
83 while (retry_count_init++ < 3) {
Martin Rothe4b9af12016-11-29 10:50:52 -070084 rk_edp_init();
85 if (rk_edp_get_edid(&edid) == 0) {
86 detected_mode = VOP_MODE_EDP;
87 break;
88 }
Ege Mihmanlibb9bdeb2018-01-07 18:03:07 -080089 if (retry_count_init == 3) {
90 printk(BIOS_WARNING,
91 "Warning: EDP initialization failed.\n");
Martin Rothe4b9af12016-11-29 10:50:52 -070092 return;
93 } else {
94 reset_edp();
95 }
Shunqian Zhengd1cec752016-05-04 16:21:36 +080096 }
Martin Rothe4b9af12016-11-29 10:50:52 -070097 break;
Nickey Yangfe122d42017-04-27 09:38:06 +080098 case VOP_MODE_MIPI:
99 printk(BIOS_DEBUG, "Attempting to setup MIPI display.\n");
100
101 rkclk_configure_mipi();
102 rkclk_configure_vop_aclk(vop_id, 200 * MHz);
103
Lin Huang25fb09b2017-11-22 09:40:50 +0800104 /*
105 * disable tx0 turnrequest, turndisable,
106 * forcetxstop, forcerxmode
107 */
Nickey Yangfe122d42017-04-27 09:38:06 +0800108 write32(&rk3399_grf->soc_con22, RK_CLRBITS(0xffff));
Nickey Yangfe122d42017-04-27 09:38:06 +0800109
Lin Huang25fb09b2017-11-22 09:40:50 +0800110 /* disable tx1 turndisable, forcetxstop, forcerxmode */
111 write32(&rk3399_grf->soc_con23, RK_CLRBITS(0xfff0));
112
113 /*
114 * enable dphy_tx1rx1_masterslavez,
115 * clear dphy_tx1rx1_enableclk,
116 * clear dphy_tx1rx1_basedir,
117 * disable tx1 turnrequest
118 */
119 write32(&rk3399_grf->soc_con24,
120 RK_CLRSETBITS(1 << 7 | 1 << 6 | 1 << 5 | 0xf,
121 1 << 7 | 0 << 6 | 0 << 5 | 0 << 0));
122
123 /* dphy_tx1rx1_enable */
124 write32(&rk3399_grf->soc_con23, RK_SETBITS(0xf));
125
126 /* select mipi-dsi0 and mipi-dsi1 signal from vop0 */
127 write32(&rk3399_grf->soc_con20,
128 RK_CLRBITS((1 << 0) | (1 << 4)));
129
Lin Huangadd76662017-11-23 08:50:03 +0800130 panel_data = mainboard_get_mipi_mode(&edid.mode);
Lin Huang25fb09b2017-11-22 09:40:50 +0800131 if (panel_data) {
132 if (panel_data->mipi_num > 1)
133 detected_mode = VOP_MODE_DUAL_MIPI;
134 else
135 detected_mode = VOP_MODE_MIPI;
136 } else {
137 printk(BIOS_WARNING, "Can not get mipi panel data\n");
138 return;
139 }
Nickey Yangfe122d42017-04-27 09:38:06 +0800140 break;
Shunqian Zhengd1cec752016-05-04 16:21:36 +0800141 default:
Nickey Yangfe122d42017-04-27 09:38:06 +0800142 printk(BIOS_WARNING, "Unsupported vop_mode, aborting.\n");
Shunqian Zhengd1cec752016-05-04 16:21:36 +0800143 return;
144 }
145
Lin Huang152e6752016-10-20 14:22:11 -0700146 if (rkclk_configure_vop_dclk(vop_id,
Shunqian Zhengd1cec752016-05-04 16:21:36 +0800147 edid.mode.pixel_clock * KHz)) {
148 printk(BIOS_WARNING, "config vop err\n");
149 return;
150 }
151
Julius Wernere74f5ea2016-10-17 18:14:41 -0700152 edid_set_framebuffer_bits_per_pixel(&edid,
153 conf->framebuffer_bits_per_pixel, 0);
Lin Huang152e6752016-10-20 14:22:11 -0700154 rkvop_mode_set(vop_id, &edid, detected_mode);
Shunqian Zhengd1cec752016-05-04 16:21:36 +0800155
Lin Huang152e6752016-10-20 14:22:11 -0700156 rkvop_prepare(vop_id, &edid);
Shunqian Zhengd1cec752016-05-04 16:21:36 +0800157
158 switch (detected_mode) {
Nickey Yangfe122d42017-04-27 09:38:06 +0800159 case VOP_MODE_MIPI:
Lin Huang25fb09b2017-11-22 09:40:50 +0800160 case VOP_MODE_DUAL_MIPI:
161 rk_mipi_prepare(&edid, panel_data);
Nickey Yangfe122d42017-04-27 09:38:06 +0800162 break;
Shunqian Zhengd1cec752016-05-04 16:21:36 +0800163 case VOP_MODE_EDP:
Lin Huanga09b3382016-10-23 14:17:25 -0700164 /* will enable edp in depthcharge */
Martin Rothe4b9af12016-11-29 10:50:52 -0700165 if (rk_edp_prepare()) {
Ege Mihmanlibb9bdeb2018-01-07 18:03:07 -0800166 if (retry_count_edp_prepare++ < 3) {
167 reset_edp();
168 /* Rerun entire init sequence */
169 goto retry_edp;
170 }
171 printk(BIOS_ERR, "EDP preparation failed.");
172 return;
Martin Rothe4b9af12016-11-29 10:50:52 -0700173 }
Nickey Yangfe122d42017-04-27 09:38:06 +0800174 break;
175 default:
Shunqian Zhengd1cec752016-05-04 16:21:36 +0800176 break;
177 }
Nickey Yangfe122d42017-04-27 09:38:06 +0800178 mainboard_power_on_backlight();
Lin Huang152e6752016-10-20 14:22:11 -0700179 set_vbe_mode_info_valid(&edid, (uintptr_t)0);
Nickey Yangfe122d42017-04-27 09:38:06 +0800180
Lin Huang079b5c62016-11-21 17:35:20 +0800181 return;
Shunqian Zhengd1cec752016-05-04 16:21:36 +0800182}