blob: a197a7f0096d831e82d9f8203d974a7d68d638a1 [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>
Patrick Rudolph73192882020-02-19 12:10:51 +010013#include <framebuffer_info.h>
Hung-Te Lin2c307a02019-02-20 14:31:23 +080014#include <gpio.h>
15#include <soc/ddp.h>
16#include <soc/dsi.h>
Tristan Shieh8db79c12018-09-07 17:26:21 +080017#include <soc/gpio.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>
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +080022#include <string.h>
Tristan Shiehbb684e02018-06-19 16:07:54 +080023
Tristan Shieh4d990ab2019-02-25 17:14:14 +080024#include "gpio.h"
Hung-Te Lin2c307a02019-02-20 14:31:23 +080025#include "panel.h"
26
Tristan Shieh4d990ab2019-02-25 17:14:14 +080027#include <arm-trusted-firmware/include/export/plat/mediatek/common/plat_params_exp.h>
28
Tristan Shieh8db79c12018-09-07 17:26:21 +080029static void configure_emmc(void)
30{
31 const gpio_t emmc_pin[] = {
32 GPIO(MSDC0_DAT0), GPIO(MSDC0_DAT1),
33 GPIO(MSDC0_DAT2), GPIO(MSDC0_DAT3),
34 GPIO(MSDC0_DAT4), GPIO(MSDC0_DAT5),
35 GPIO(MSDC0_DAT6), GPIO(MSDC0_DAT7),
36 GPIO(MSDC0_CMD), GPIO(MSDC0_RSTB),
37 };
38
39 for (size_t i = 0; i < ARRAY_SIZE(emmc_pin); i++)
40 gpio_set_pull(emmc_pin[i], GPIO_PULL_ENABLE, GPIO_PULL_UP);
41}
42
Tristan Shieh71ae5822018-09-26 14:33:54 +080043static void configure_usb(void)
44{
45 setup_usb_host();
46}
47
Jiaxin Yu30bc9f42019-04-23 20:45:50 +080048static void configure_audio(void)
49{
50 /* Audio PWR*/
51 mtcmos_audio_power_on();
52
53 /* SoC I2S */
54 gpio_set_mode(GPIO(CAM_RST0), PAD_CAM_RST0_FUNC_I2S2_LRCK);
55 gpio_set_mode(GPIO(CAM_PDN1), PAD_CAM_PDN1_FUNC_I2S2_BCK);
56 gpio_set_mode(GPIO(CAM_PDN0), PAD_CAM_PDN0_FUNC_I2S2_MCK);
57 gpio_set_mode(GPIO(EINT3), PAD_EINT3_FUNC_I2S3_DO);
58}
Hung-Te Lin2c307a02019-02-20 14:31:23 +080059
Hung-Te Lin7fc22812020-07-24 08:49:41 +080060static void configure_ec(void)
61{
62 /* EC may need SKU ID to identify if it is clamshell or convertible. */
63 if (CONFIG(BOARD_GOOGLE_JACUZZI_COMMON))
64 google_chromeec_set_sku_id(sku_id());
65}
66
Hung-Te Lin2c307a02019-02-20 14:31:23 +080067/* Default implementation for boards without panels defined yet. */
68struct panel_description __weak *get_panel_description(int panel_id)
69{
70 printk(BIOS_ERR, "%s: ERROR: No panels defined for board: %s.\n",
71 __func__, CONFIG_MAINBOARD_PART_NUMBER);
72 return NULL;
73}
74
75/* Set up backlight control pins as output pin and power-off by default */
76static void configure_panel_backlight(void)
77{
78 gpio_output(GPIO(PERIPHERAL_EN13), 0);
79 gpio_output(GPIO(DISP_PWM), 0);
80}
81
82static void power_on_panel(struct panel_description *panel)
83{
84 if (panel->power_on) {
85 panel->power_on();
86 return;
87 }
88
89 /* Default power sequence for most panels. */
90 gpio_output(GPIO_LCM_RST_1V8, 0);
91 gpio_output(GPIO_PPVARP_LCD_EN, 1);
92 gpio_output(GPIO_PPVARN_LCD_EN, 1);
93 gpio_output(GPIO_PP1800_LCM_EN, 1);
94 gpio_output(GPIO_PP3300_LCM_EN, 1);
Tao Xiaf3c0a012020-11-11 15:32:46 +080095 mdelay(15);
Hung-Te Lin2c307a02019-02-20 14:31:23 +080096 gpio_output(GPIO_LCM_RST_1V8, 1);
97 mdelay(6);
98}
99
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800100struct panel_description *get_panel_from_cbfs(struct panel_description *desc)
101{
102 /* The CBFS name will be panel-{MANUFACTURER}-${PANEL_NAME},
103 * where MANUFACTURER is 3 characters and PANEL_NAME is usually
104 * 13 characters.
105 */
106 char cbfs_name[64];
107 static union {
108 u8 raw[4 * 1024]; /* Most panels only need < 2K. */
109 struct panel_serializable_data s;
110 } buffer;
111
112 if (!desc->name)
113 return NULL;
114
115 snprintf(cbfs_name, sizeof(cbfs_name), "panel-%s", desc->name);
Julius Werner834b3ec2020-03-04 16:52:08 -0800116 if (cbfs_load(cbfs_name, buffer.raw, sizeof(buffer)))
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800117 desc->s = &buffer.s;
118 else
119 printk(BIOS_ERR, "Missing %s in CBFS.\n", cbfs_name);
120
121 return desc->s ? desc : NULL;
122}
123
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800124static struct panel_description *get_active_panel(void)
125{
126 /* TODO(hungte) Create a dedicated panel_id() in board_id.c */
127 int panel_id = sku_id() >> 4;
128
129 struct panel_description *panel = get_panel_description(panel_id);
130 if (!panel) {
131 printk(BIOS_ERR, "%s: Panel %d is not supported.\n",
132 __func__, panel_id);
133 return NULL;
134 }
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800135 assert(panel->s);
136
137 const struct edid *edid = &panel->s->edid;
138 const char *name = edid->ascii_string;
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800139 if (name[0] == '\0')
140 name = "unknown name";
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800141 printk(BIOS_INFO, "%s: Found ID %d: '%s %s' %dx%d@%dHz\n", __func__,
142 panel_id, edid->manufacturer_name, name, edid->mode.ha,
143 edid->mode.va, edid->mode.refresh);
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800144 return panel;
145}
146
147static bool configure_display(void)
148{
149 struct panel_description *panel = get_active_panel();
150 if (!panel)
151 return false;
152
153 mtcmos_display_power_on();
154 mtcmos_protect_display_bus();
155 configure_panel_backlight();
156 power_on_panel(panel);
157
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800158 struct edid *edid = &panel->s->edid;
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800159 edid_set_framebuffer_bits_per_pixel(edid, 32, 0);
160 mtk_ddp_init();
161 u32 mipi_dsi_flags = (MIPI_DSI_MODE_VIDEO |
162 MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
163 MIPI_DSI_MODE_LPM);
Paul Ma6d500a22020-05-08 13:16:04 +0800164 if (CONFIG(DRIVER_ANALOGIX_ANX7625))
165 mipi_dsi_flags |= MIPI_DSI_MODE_EOT_PACKET;
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 }
171 mtk_ddp_mode_set(edid);
Patrick Rudolph8b56c8c2020-02-19 12:57:00 +0100172 struct fb_info *info = fb_new_framebuffer_info_from_edid(edid, 0);
Patrick Rudolph73192882020-02-19 12:10:51 +0100173 if (info)
174 fb_set_orientation(info, panel->s->orientation);
175
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800176 return true;
177}
178
Tristan Shieh4d990ab2019-02-25 17:14:14 +0800179static void register_reset_to_bl31(void)
180{
181 static struct bl_aux_param_gpio param_reset = {
182 .h = { .type = BL_AUX_PARAM_MTK_RESET_GPIO },
183 .gpio = { .polarity = ARM_TF_GPIO_LEVEL_HIGH },
184 };
185
186 param_reset.gpio.index = GPIO_RESET.id;
187 register_bl31_aux_param(&param_reset.h);
188}
189
Tristan Shiehbb684e02018-06-19 16:07:54 +0800190static void mainboard_init(struct device *dev)
191{
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800192 if (display_init_required()) {
193 printk(BIOS_INFO, "%s: Starting display init.\n", __func__);
194 if (!configure_display())
195 printk(BIOS_ERR, "%s: Failed to init display.\n",
196 __func__);
197 } else {
198 printk(BIOS_INFO, "%s: Skipped display init.\n", __func__);
199 }
200
Tristan Shieh8db79c12018-09-07 17:26:21 +0800201 configure_emmc();
Tristan Shieh71ae5822018-09-26 14:33:54 +0800202 configure_usb();
Jiaxin Yu30bc9f42019-04-23 20:45:50 +0800203 configure_audio();
Hung-Te Lin7fc22812020-07-24 08:49:41 +0800204 configure_ec();
Dawei Chien2422f8c2019-05-30 11:55:10 +0800205 if (spm_init())
206 printk(BIOS_ERR,
207 "SPM initialization failed, suspend/resume may fail.\n");
Tristan Shieh4d990ab2019-02-25 17:14:14 +0800208
209 register_reset_to_bl31();
Tristan Shiehbb684e02018-06-19 16:07:54 +0800210}
211
212static void mainboard_enable(struct device *dev)
213{
214 dev->ops->init = &mainboard_init;
215}
216
217struct chip_operations mainboard_ops = {
218 .name = CONFIG_MAINBOARD_PART_NUMBER,
219 .enable_dev = mainboard_enable,
220};