blob: bc70db5bcfe9bc2c9e9cf8a7a2c94073d9c8c06f [file] [log] [blame]
Angel Pons11ba3532020-04-05 13:21:58 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Tristan Shiehbb684e02018-06-19 16:07:54 +08002
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +08003#include <assert.h>
Hung-Te Lin2c307a02019-02-20 14:31:23 +08004#include <boardid.h>
5#include <bootmode.h>
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +08006#include <cbfs.h>
Hung-Te Lin2c307a02019-02-20 14:31:23 +08007#include <console/console.h>
8#include <delay.h>
Tristan Shiehbb684e02018-06-19 16:07:54 +08009#include <device/device.h>
Hung-Te Lin7fc22812020-07-24 08:49:41 +080010#include <ec/google/chromeec/ec.h>
Hung-Te Lin2c307a02019-02-20 14:31:23 +080011#include <edid.h>
Patrick Rudolph73192882020-02-19 12:10:51 +010012#include <framebuffer_info.h>
Hung-Te Lin2c307a02019-02-20 14:31:23 +080013#include <gpio.h>
Kyösti Mälkkib78e4622022-12-15 22:12:29 +020014#include <identity.h>
Hung-Te Lina01f8bc2022-09-06 14:32:05 +080015#include <soc/bl31.h>
Hung-Te Lin2c307a02019-02-20 14:31:23 +080016#include <soc/ddp.h>
17#include <soc/dsi.h>
Tristan Shiehbb684e02018-06-19 16:07:54 +080018#include <soc/mmu_operations.h>
Jiaxin Yu30bc9f42019-04-23 20:45:50 +080019#include <soc/mtcmos.h>
Dawei Chien2422f8c2019-05-30 11:55:10 +080020#include <soc/spm.h>
Tristan Shieh71ae5822018-09-26 14:33:54 +080021#include <soc/usb.h>
Elyes Haouasbdd03c22024-05-27 11:20:07 +020022#include <stdio.h>
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +080023#include <string.h>
Tristan Shiehbb684e02018-06-19 16:07:54 +080024
Tristan Shieh4d990ab2019-02-25 17:14:14 +080025#include "gpio.h"
Hung-Te Lin2c307a02019-02-20 14:31:23 +080026#include "panel.h"
27
Tristan Shieh8db79c12018-09-07 17:26:21 +080028static void configure_emmc(void)
29{
30 const gpio_t emmc_pin[] = {
31 GPIO(MSDC0_DAT0), GPIO(MSDC0_DAT1),
32 GPIO(MSDC0_DAT2), GPIO(MSDC0_DAT3),
33 GPIO(MSDC0_DAT4), GPIO(MSDC0_DAT5),
34 GPIO(MSDC0_DAT6), GPIO(MSDC0_DAT7),
35 GPIO(MSDC0_CMD), GPIO(MSDC0_RSTB),
36 };
37
38 for (size_t i = 0; i < ARRAY_SIZE(emmc_pin); i++)
39 gpio_set_pull(emmc_pin[i], GPIO_PULL_ENABLE, GPIO_PULL_UP);
40}
41
Tristan Shieh71ae5822018-09-26 14:33:54 +080042static void configure_usb(void)
43{
44 setup_usb_host();
45}
46
Jiaxin Yu30bc9f42019-04-23 20:45:50 +080047static void configure_audio(void)
48{
49 /* Audio PWR*/
50 mtcmos_audio_power_on();
51
52 /* SoC I2S */
53 gpio_set_mode(GPIO(CAM_RST0), PAD_CAM_RST0_FUNC_I2S2_LRCK);
54 gpio_set_mode(GPIO(CAM_PDN1), PAD_CAM_PDN1_FUNC_I2S2_BCK);
55 gpio_set_mode(GPIO(CAM_PDN0), PAD_CAM_PDN0_FUNC_I2S2_MCK);
56 gpio_set_mode(GPIO(EINT3), PAD_EINT3_FUNC_I2S3_DO);
57}
Hung-Te Lin2c307a02019-02-20 14:31:23 +080058
Hung-Te Lin7fc22812020-07-24 08:49:41 +080059static void configure_ec(void)
60{
61 /* EC may need SKU ID to identify if it is clamshell or convertible. */
62 if (CONFIG(BOARD_GOOGLE_JACUZZI_COMMON))
63 google_chromeec_set_sku_id(sku_id());
64}
65
Hung-Te Lin2c307a02019-02-20 14:31:23 +080066/* Default implementation for boards without panels defined yet. */
67struct panel_description __weak *get_panel_description(int panel_id)
68{
69 printk(BIOS_ERR, "%s: ERROR: No panels defined for board: %s.\n",
Kyösti Mälkkib78e4622022-12-15 22:12:29 +020070 __func__, mainboard_part_number);
Hung-Te Lin2c307a02019-02-20 14:31:23 +080071 return NULL;
72}
73
74/* Set up backlight control pins as output pin and power-off by default */
75static void configure_panel_backlight(void)
76{
77 gpio_output(GPIO(PERIPHERAL_EN13), 0);
78 gpio_output(GPIO(DISP_PWM), 0);
79}
80
81static void power_on_panel(struct panel_description *panel)
82{
83 if (panel->power_on) {
84 panel->power_on();
85 return;
86 }
87
88 /* Default power sequence for most panels. */
89 gpio_output(GPIO_LCM_RST_1V8, 0);
90 gpio_output(GPIO_PPVARP_LCD_EN, 1);
91 gpio_output(GPIO_PPVARN_LCD_EN, 1);
92 gpio_output(GPIO_PP1800_LCM_EN, 1);
93 gpio_output(GPIO_PP3300_LCM_EN, 1);
Tao Xiaf3c0a012020-11-11 15:32:46 +080094 mdelay(15);
Hung-Te Lin2c307a02019-02-20 14:31:23 +080095 gpio_output(GPIO_LCM_RST_1V8, 1);
96 mdelay(6);
97}
98
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +080099struct panel_description *get_panel_from_cbfs(struct panel_description *desc)
100{
101 /* The CBFS name will be panel-{MANUFACTURER}-${PANEL_NAME},
102 * where MANUFACTURER is 3 characters and PANEL_NAME is usually
103 * 13 characters.
104 */
105 char cbfs_name[64];
106 static union {
107 u8 raw[4 * 1024]; /* Most panels only need < 2K. */
108 struct panel_serializable_data s;
109 } buffer;
110
111 if (!desc->name)
112 return NULL;
113
114 snprintf(cbfs_name, sizeof(cbfs_name), "panel-%s", desc->name);
Julius Werner834b3ec2020-03-04 16:52:08 -0800115 if (cbfs_load(cbfs_name, buffer.raw, sizeof(buffer)))
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800116 desc->s = &buffer.s;
117 else
118 printk(BIOS_ERR, "Missing %s in CBFS.\n", cbfs_name);
119
120 return desc->s ? desc : NULL;
121}
122
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800123static struct panel_description *get_active_panel(void)
124{
125 /* TODO(hungte) Create a dedicated panel_id() in board_id.c */
xuxinxiong3ced5282021-03-26 22:53:35 +0800126 int panel_id = sku_id() >> 4 & 0x0F;
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800127
128 struct panel_description *panel = get_panel_description(panel_id);
129 if (!panel) {
130 printk(BIOS_ERR, "%s: Panel %d is not supported.\n",
131 __func__, panel_id);
132 return NULL;
133 }
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800134 assert(panel->s);
135
136 const struct edid *edid = &panel->s->edid;
137 const char *name = edid->ascii_string;
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800138 if (name[0] == '\0')
139 name = "unknown name";
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800140 printk(BIOS_INFO, "%s: Found ID %d: '%s %s' %dx%d@%dHz\n", __func__,
141 panel_id, edid->manufacturer_name, name, edid->mode.ha,
142 edid->mode.va, edid->mode.refresh);
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800143 return panel;
144}
145
146static bool configure_display(void)
147{
148 struct panel_description *panel = get_active_panel();
149 if (!panel)
150 return false;
151
152 mtcmos_display_power_on();
153 mtcmos_protect_display_bus();
154 configure_panel_backlight();
155 power_on_panel(panel);
156
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800157 struct edid *edid = &panel->s->edid;
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800158 edid_set_framebuffer_bits_per_pixel(edid, 32, 0);
159 mtk_ddp_init();
160 u32 mipi_dsi_flags = (MIPI_DSI_MODE_VIDEO |
161 MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
162 MIPI_DSI_MODE_LPM);
Paul Ma6d500a22020-05-08 13:16:04 +0800163 if (CONFIG(DRIVER_ANALOGIX_ANX7625))
Jitao Shib9239312021-03-04 21:52:24 +0800164 mipi_dsi_flags |= MIPI_DSI_MODE_EOT_PACKET |
165 MIPI_DSI_MODE_LINE_END;
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800166 if (mtk_dsi_init(mipi_dsi_flags, MIPI_DSI_FMT_RGB888, 4, edid,
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800167 panel->s->init) < 0) {
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800168 printk(BIOS_ERR, "%s: Failed in DSI init.\n", __func__);
169 return false;
170 }
Jitao Shib32e4d62020-09-25 10:36:29 +0800171
172 if (panel->post_power_on)
173 panel->post_power_on();
174
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800175 mtk_ddp_mode_set(edid);
Patrick Rudolph8b56c8c2020-02-19 12:57:00 +0100176 struct fb_info *info = fb_new_framebuffer_info_from_edid(edid, 0);
Patrick Rudolph73192882020-02-19 12:10:51 +0100177 if (info)
Julius Werner1f84b2c2021-09-01 16:27:58 -0700178 fb_set_orientation(info, panel->orientation);
Patrick Rudolph73192882020-02-19 12:10:51 +0100179
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800180 return true;
181}
182
Tristan Shiehbb684e02018-06-19 16:07:54 +0800183static void mainboard_init(struct device *dev)
184{
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800185 if (display_init_required()) {
186 printk(BIOS_INFO, "%s: Starting display init.\n", __func__);
187 if (!configure_display())
188 printk(BIOS_ERR, "%s: Failed to init display.\n",
189 __func__);
190 } else {
191 printk(BIOS_INFO, "%s: Skipped display init.\n", __func__);
192 }
193
Tristan Shieh8db79c12018-09-07 17:26:21 +0800194 configure_emmc();
Tristan Shieh71ae5822018-09-26 14:33:54 +0800195 configure_usb();
Jiaxin Yu30bc9f42019-04-23 20:45:50 +0800196 configure_audio();
Hung-Te Lin7fc22812020-07-24 08:49:41 +0800197 configure_ec();
Dawei Chien2422f8c2019-05-30 11:55:10 +0800198 if (spm_init())
199 printk(BIOS_ERR,
200 "SPM initialization failed, suspend/resume may fail.\n");
Tristan Shieh4d990ab2019-02-25 17:14:14 +0800201
Hung-Te Lina01f8bc2022-09-06 14:32:05 +0800202 if (CONFIG(ARM64_USE_ARM_TRUSTED_FIRMWARE))
203 register_reset_to_bl31(GPIO_RESET.id, true);
Tristan Shiehbb684e02018-06-19 16:07:54 +0800204}
205
206static void mainboard_enable(struct device *dev)
207{
208 dev->ops->init = &mainboard_init;
209}
210
211struct chip_operations mainboard_ops = {
Tristan Shiehbb684e02018-06-19 16:07:54 +0800212 .enable_dev = mainboard_enable,
213};