blob: 4220810d17d6c8601a8d2390aa5aa6d04bcb0cf1 [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>
Tristan Shieh4d990ab2019-02-25 17:14:14 +08004#include <bl31.h>
Hung-Te Lin2c307a02019-02-20 14:31:23 +08005#include <boardid.h>
6#include <bootmode.h>
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +08007#include <cbfs.h>
Hung-Te Lin2c307a02019-02-20 14:31:23 +08008#include <console/console.h>
9#include <delay.h>
Tristan Shiehbb684e02018-06-19 16:07:54 +080010#include <device/device.h>
Hung-Te Lin7fc22812020-07-24 08:49:41 +080011#include <ec/google/chromeec/ec.h>
Hung-Te Lin2c307a02019-02-20 14:31:23 +080012#include <edid.h>
13#include <gpio.h>
14#include <soc/ddp.h>
15#include <soc/dsi.h>
Tristan Shieh8db79c12018-09-07 17:26:21 +080016#include <soc/gpio.h>
Tristan Shiehbb684e02018-06-19 16:07:54 +080017#include <soc/mmu_operations.h>
Jiaxin Yu30bc9f42019-04-23 20:45:50 +080018#include <soc/mtcmos.h>
Dawei Chien2422f8c2019-05-30 11:55:10 +080019#include <soc/spm.h>
Tristan Shieh71ae5822018-09-26 14:33:54 +080020#include <soc/usb.h>
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +080021#include <string.h>
Tristan Shiehbb684e02018-06-19 16:07:54 +080022
Tristan Shieh4d990ab2019-02-25 17:14:14 +080023#include "gpio.h"
Hung-Te Lin2c307a02019-02-20 14:31:23 +080024#include "panel.h"
25
Tristan Shieh4d990ab2019-02-25 17:14:14 +080026#include <arm-trusted-firmware/include/export/plat/mediatek/common/plat_params_exp.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",
70 __func__, CONFIG_MAINBOARD_PART_NUMBER);
71 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 */
126 int panel_id = sku_id() >> 4;
127
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))
164 mipi_dsi_flags |= MIPI_DSI_MODE_EOT_PACKET;
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800165 if (mtk_dsi_init(mipi_dsi_flags, MIPI_DSI_FMT_RGB888, 4, edid,
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800166 panel->s->init) < 0) {
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800167 printk(BIOS_ERR, "%s: Failed in DSI init.\n", __func__);
168 return false;
169 }
170 mtk_ddp_mode_set(edid);
171 set_vbe_mode_info_valid(edid, 0);
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800172 set_vbe_framebuffer_orientation(panel->s->orientation);
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800173 return true;
174}
175
Tristan Shieh4d990ab2019-02-25 17:14:14 +0800176static void register_reset_to_bl31(void)
177{
178 static struct bl_aux_param_gpio param_reset = {
179 .h = { .type = BL_AUX_PARAM_MTK_RESET_GPIO },
180 .gpio = { .polarity = ARM_TF_GPIO_LEVEL_HIGH },
181 };
182
183 param_reset.gpio.index = GPIO_RESET.id;
184 register_bl31_aux_param(&param_reset.h);
185}
186
Tristan Shiehbb684e02018-06-19 16:07:54 +0800187static void mainboard_init(struct device *dev)
188{
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800189 if (display_init_required()) {
190 printk(BIOS_INFO, "%s: Starting display init.\n", __func__);
191 if (!configure_display())
192 printk(BIOS_ERR, "%s: Failed to init display.\n",
193 __func__);
194 } else {
195 printk(BIOS_INFO, "%s: Skipped display init.\n", __func__);
196 }
197
Tristan Shieh8db79c12018-09-07 17:26:21 +0800198 configure_emmc();
Tristan Shieh71ae5822018-09-26 14:33:54 +0800199 configure_usb();
Jiaxin Yu30bc9f42019-04-23 20:45:50 +0800200 configure_audio();
Hung-Te Lin7fc22812020-07-24 08:49:41 +0800201 configure_ec();
Dawei Chien2422f8c2019-05-30 11:55:10 +0800202 if (spm_init())
203 printk(BIOS_ERR,
204 "SPM initialization failed, suspend/resume may fail.\n");
Tristan Shieh4d990ab2019-02-25 17:14:14 +0800205
206 register_reset_to_bl31();
Tristan Shiehbb684e02018-06-19 16:07:54 +0800207}
208
209static void mainboard_enable(struct device *dev)
210{
211 dev->ops->init = &mainboard_init;
212}
213
214struct chip_operations mainboard_ops = {
215 .name = CONFIG_MAINBOARD_PART_NUMBER,
216 .enable_dev = mainboard_enable,
217};