blob: efcd49e078731bc4f0250a47a08bf3dff893308a [file] [log] [blame]
Angel Pons11ba3532020-04-05 13:21:58 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Tristan Shiehbb684e02018-06-19 16:07:54 +08003
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +08004#include <assert.h>
Tristan Shieh4d990ab2019-02-25 17:14:14 +08005#include <bl31.h>
Hung-Te Lin2c307a02019-02-20 14:31:23 +08006#include <boardid.h>
7#include <bootmode.h>
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +08008#include <cbfs.h>
Hung-Te Lin2c307a02019-02-20 14:31:23 +08009#include <console/console.h>
10#include <delay.h>
Tristan Shiehbb684e02018-06-19 16:07:54 +080011#include <device/device.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
59/* Default implementation for boards without panels defined yet. */
60struct panel_description __weak *get_panel_description(int panel_id)
61{
62 printk(BIOS_ERR, "%s: ERROR: No panels defined for board: %s.\n",
63 __func__, CONFIG_MAINBOARD_PART_NUMBER);
64 return NULL;
65}
66
67/* Set up backlight control pins as output pin and power-off by default */
68static void configure_panel_backlight(void)
69{
70 gpio_output(GPIO(PERIPHERAL_EN13), 0);
71 gpio_output(GPIO(DISP_PWM), 0);
72}
73
74static void power_on_panel(struct panel_description *panel)
75{
76 if (panel->power_on) {
77 panel->power_on();
78 return;
79 }
80
81 /* Default power sequence for most panels. */
82 gpio_output(GPIO_LCM_RST_1V8, 0);
83 gpio_output(GPIO_PPVARP_LCD_EN, 1);
84 gpio_output(GPIO_PPVARN_LCD_EN, 1);
85 gpio_output(GPIO_PP1800_LCM_EN, 1);
86 gpio_output(GPIO_PP3300_LCM_EN, 1);
87 mdelay(6);
88 gpio_output(GPIO_LCM_RST_1V8, 1);
89 mdelay(6);
90}
91
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +080092struct panel_description *get_panel_from_cbfs(struct panel_description *desc)
93{
94 /* The CBFS name will be panel-{MANUFACTURER}-${PANEL_NAME},
95 * where MANUFACTURER is 3 characters and PANEL_NAME is usually
96 * 13 characters.
97 */
98 char cbfs_name[64];
99 static union {
100 u8 raw[4 * 1024]; /* Most panels only need < 2K. */
101 struct panel_serializable_data s;
102 } buffer;
103
104 if (!desc->name)
105 return NULL;
106
107 snprintf(cbfs_name, sizeof(cbfs_name), "panel-%s", desc->name);
108 if (cbfs_boot_load_file(cbfs_name, buffer.raw, sizeof(buffer),
109 CBFS_TYPE_STRUCT))
110 desc->s = &buffer.s;
111 else
112 printk(BIOS_ERR, "Missing %s in CBFS.\n", cbfs_name);
113
114 return desc->s ? desc : NULL;
115}
116
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800117static struct panel_description *get_active_panel(void)
118{
119 /* TODO(hungte) Create a dedicated panel_id() in board_id.c */
120 int panel_id = sku_id() >> 4;
121
122 struct panel_description *panel = get_panel_description(panel_id);
123 if (!panel) {
124 printk(BIOS_ERR, "%s: Panel %d is not supported.\n",
125 __func__, panel_id);
126 return NULL;
127 }
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800128 assert(panel->s);
129
130 const struct edid *edid = &panel->s->edid;
131 const char *name = edid->ascii_string;
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800132 if (name[0] == '\0')
133 name = "unknown name";
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800134 printk(BIOS_INFO, "%s: Found ID %d: '%s %s' %dx%d@%dHz\n", __func__,
135 panel_id, edid->manufacturer_name, name, edid->mode.ha,
136 edid->mode.va, edid->mode.refresh);
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800137 return panel;
138}
139
140static bool configure_display(void)
141{
142 struct panel_description *panel = get_active_panel();
143 if (!panel)
144 return false;
145
146 mtcmos_display_power_on();
147 mtcmos_protect_display_bus();
148 configure_panel_backlight();
149 power_on_panel(panel);
150
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800151 struct edid *edid = &panel->s->edid;
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800152 edid_set_framebuffer_bits_per_pixel(edid, 32, 0);
153 mtk_ddp_init();
154 u32 mipi_dsi_flags = (MIPI_DSI_MODE_VIDEO |
155 MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
156 MIPI_DSI_MODE_LPM);
Paul Ma6d500a22020-05-08 13:16:04 +0800157 if (CONFIG(DRIVER_ANALOGIX_ANX7625))
158 mipi_dsi_flags |= MIPI_DSI_MODE_EOT_PACKET;
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800159 if (mtk_dsi_init(mipi_dsi_flags, MIPI_DSI_FMT_RGB888, 4, edid,
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800160 panel->s->init) < 0) {
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800161 printk(BIOS_ERR, "%s: Failed in DSI init.\n", __func__);
162 return false;
163 }
164 mtk_ddp_mode_set(edid);
165 set_vbe_mode_info_valid(edid, 0);
Hung-Te Lin9ede2ff2019-08-15 09:43:55 +0800166 set_vbe_framebuffer_orientation(panel->s->orientation);
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800167 return true;
168}
169
Tristan Shieh4d990ab2019-02-25 17:14:14 +0800170static void register_reset_to_bl31(void)
171{
172 static struct bl_aux_param_gpio param_reset = {
173 .h = { .type = BL_AUX_PARAM_MTK_RESET_GPIO },
174 .gpio = { .polarity = ARM_TF_GPIO_LEVEL_HIGH },
175 };
176
177 param_reset.gpio.index = GPIO_RESET.id;
178 register_bl31_aux_param(&param_reset.h);
179}
180
Tristan Shiehbb684e02018-06-19 16:07:54 +0800181static void mainboard_init(struct device *dev)
182{
Hung-Te Lin2c307a02019-02-20 14:31:23 +0800183 if (display_init_required()) {
184 printk(BIOS_INFO, "%s: Starting display init.\n", __func__);
185 if (!configure_display())
186 printk(BIOS_ERR, "%s: Failed to init display.\n",
187 __func__);
188 } else {
189 printk(BIOS_INFO, "%s: Skipped display init.\n", __func__);
190 }
191
Tristan Shieh8db79c12018-09-07 17:26:21 +0800192 configure_emmc();
Tristan Shieh71ae5822018-09-26 14:33:54 +0800193 configure_usb();
Jiaxin Yu30bc9f42019-04-23 20:45:50 +0800194 configure_audio();
Dawei Chien2422f8c2019-05-30 11:55:10 +0800195 if (spm_init())
196 printk(BIOS_ERR,
197 "SPM initialization failed, suspend/resume may fail.\n");
Tristan Shieh4d990ab2019-02-25 17:14:14 +0800198
199 register_reset_to_bl31();
Tristan Shiehbb684e02018-06-19 16:07:54 +0800200}
201
202static void mainboard_enable(struct device *dev)
203{
204 dev->ops->init = &mainboard_init;
205}
206
207struct chip_operations mainboard_ops = {
208 .name = CONFIG_MAINBOARD_PART_NUMBER,
209 .enable_dev = mainboard_enable,
210};