1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
/* SPDX-License-Identifier: GPL-2.0-only */
#include <assert.h>
#include <console/console.h>
#include <delay.h>
#include <drivers/analogix/anx7625/anx7625.h>
#include <drivers/parade/ps8640/ps8640.h>
#include <gpio.h>
#include <soc/ddp.h>
#include <soc/dsi.h>
#include <soc/gpio_common.h>
#include <soc/regulator.h>
#include <soc/i2c.h>
#include <soc/mtcmos.h>
#include "display.h"
#include "gpio.h"
/* Bridge functions */
static void bridge_ps8640_power_on(void)
{
/* Set VRF12 to 1.2V and VCN33 to 3.3V */
mainboard_set_regulator_vol(MTK_REGULATOR_VRF12, 1200000);
mainboard_set_regulator_vol(MTK_REGULATOR_VCN33, 3300000);
udelay(200);
/* Turn on bridge */
gpio_output(GPIO_EDPBRDG_PWREN, 1);
gpio_output(GPIO_EDPBRDG_RST_L, 0);
mdelay(2);
gpio_output(GPIO_EDPBRDG_RST_L, 1);
}
static int bridge_ps8640_get_edid(u8 i2c_bus, struct edid *edid)
{
const u8 chip = 0x8;
if (ps8640_init(i2c_bus, chip) < 0) {
printk(BIOS_ERR, "%s: Can't init PS8640 bridge\n", __func__);
return -1;
}
if (ps8640_get_edid(i2c_bus, chip, edid) < 0) {
printk(BIOS_ERR, "%s: Can't get panel's edid\n", __func__);
return -1;
}
return 0;
}
static int bridge_ps8640_post_power_on(u8 i2c_bus, struct edid *edid)
{
/* Do nothing */
return 0;
}
static void bridge_anx7625_power_on(void)
{
/* Turn on bridge */
gpio_output(GPIO_EDPBRDG_RST_L, 0);
gpio_output(GPIO_EN_PP1000_EDPBRDG, 1);
gpio_output(GPIO_EN_PP1800_EDPBRDG, 1);
gpio_output(GPIO_EN_PP3300_EDPBRDG, 1);
mdelay(14);
gpio_output(GPIO_EDPBRDG_PWREN, 1);
mdelay(10);
gpio_output(GPIO_EDPBRDG_RST_L, 1);
}
static int bridge_anx7625_get_edid(u8 i2c_bus, struct edid *edid)
{
if (anx7625_init(i2c_bus) < 0) {
printk(BIOS_ERR, "%s: Can't init ANX7625 bridge\n", __func__);
return -1;
}
if (anx7625_dp_get_edid(i2c_bus, edid) < 0) {
printk(BIOS_ERR, "%s: Can't get panel's edid\n", __func__);
return -1;
}
return 0;
}
static int bridge_anx7625_post_power_on(u8 i2c_bus, struct edid *edid)
{
return anx7625_dp_start(i2c_bus, edid);
}
/* Display function */
static void backlight_control(void)
{
/* Disable backlight before turning on bridge */
gpio_output(GPIO_AP_EDP_BKLTEN, 0);
gpio_output(GPIO_BL_PWM_1V8, 0);
gpio_output(GPIO_EN_PP3300_DISP_X, 1);
}
static const struct edp_bridge anx7625_bridge = {
.power_on = bridge_anx7625_power_on,
.get_edid = bridge_anx7625_get_edid,
.post_power_on = bridge_anx7625_post_power_on,
};
static const struct edp_bridge ps8640_bridge = {
.power_on = bridge_ps8640_power_on,
.get_edid = bridge_ps8640_get_edid,
.post_power_on = bridge_ps8640_post_power_on,
};
_Static_assert(CONFIG(BOARD_GOOGLE_KINGLER_COMMON) + CONFIG(BOARD_GOOGLE_KRABBY_COMMON) == 1,
"Exactly one of KINGLER and KRABBY must be set");
int configure_display(void)
{
struct edid edid;
const u8 i2c_bus = I2C0;
const struct edp_bridge *bridge;
if (CONFIG(BOARD_GOOGLE_KINGLER_COMMON))
bridge = &anx7625_bridge;
else /* BOARD_GOOGLE_KRABBY_COMMON */
bridge = &ps8640_bridge;
printk(BIOS_INFO, "%s: Starting display init\n", __func__);
mtk_i2c_bus_init(i2c_bus, I2C_SPEED_FAST);
/* Set up backlight control pins as output pin and power-off by default */
backlight_control();
assert(bridge->power_on);
bridge->power_on();
assert(bridge->get_edid);
if (bridge->get_edid(i2c_bus, &edid) < 0) {
printk(BIOS_ERR, "%s: Failed to get edid\n", __func__);
return -1;
}
const char *name = edid.ascii_string;
if (name[0] == '\0')
name = "unknown name";
printk(BIOS_INFO, "%s: '%s %s' %dx%d@%dHz\n", __func__,
edid.manufacturer_name, name, edid.mode.ha, edid.mode.va,
edid.mode.refresh);
mtcmos_display_power_on();
mtcmos_protect_display_bus();
edid_set_framebuffer_bits_per_pixel(&edid, 32, 0);
mtk_ddp_init();
u32 mipi_dsi_flags = (MIPI_DSI_MODE_VIDEO |
MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
MIPI_DSI_MODE_LPM |
MIPI_DSI_MODE_EOT_PACKET);
if (mtk_dsi_init(mipi_dsi_flags, MIPI_DSI_FMT_RGB888, 4, &edid, NULL) < 0) {
printk(BIOS_ERR, "%s: Failed in DSI init\n", __func__);
return -1;
}
if (bridge->post_power_on(i2c_bus, &edid) < 0) {
printk(BIOS_ERR, "%s: Failed to post power on bridge\n", __func__);
return -1;
}
mtk_ddp_mode_set(&edid);
fb_new_framebuffer_info_from_edid(&edid, (uintptr_t)0);
return 0;
}
|