blob: 55ef91aad13f57b4b054af562132c4707acafd4f [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
#include <boardid.h>
#include <bootmode.h>
#include <console/console.h>
#include <delay.h>
#include <device/device.h>
#include <drivers/parade/ps8640/ps8640.h>
#include <edid.h>
#include <gpio.h>
#include <soc/da9212.h>
#include <soc/ddp.h>
#include <soc/dsi.h>
#include <soc/i2c.h>
#include <soc/mt6311.h>
#include <soc/mt6391.h>
#include <soc/mtcmos.h>
#include <soc/pll.h>
#include <soc/usb.h>
#include <framebuffer_info.h>
enum {
CODEC_I2C_BUS = 0,
EXT_BUCK_I2C_BUS = 1,
};
static void configure_ext_buck(void)
{
mtk_i2c_bus_init(EXT_BUCK_I2C_BUS);
switch (board_id() + CONFIG_BOARD_ID_ADJUSTMENT) {
case 3:
case 4:
/* rev-3 and rev-4 use mt6311 as external buck */
gpio_output(GPIO(EINT15), 1);
udelay(500);
mt6311_probe(EXT_BUCK_I2C_BUS);
break;
case 2:
default:
/* rev-2 and rev-5 use da9212 as external buck */
mt6391_gpio_output(MT6391_KP_ROW3, 1); /* DA9212_IC_EN */
mt6391_gpio_output(MT6391_KP_ROW4, 1); /* DA9212_EN_A */
udelay(500); /* add 500us delay for powering on da9212 */
da9212_probe(EXT_BUCK_I2C_BUS);
break;
}
}
static void configure_touchscreen(void)
{
/* Pull low reset gpio for 500us and then pull high */
if (board_id() + CONFIG_BOARD_ID_ADJUSTMENT >= 7) {
gpio_output(GPIO(PCM_SYNC), 0);
udelay(500);
gpio_output(GPIO(PCM_SYNC), 1);
}
}
static void configure_audio(void)
{
mtcmos_audio_power_on();
/* vgp1 set to 1.8V */
mt6391_configure_ldo(LDO_VCAMD, LDO_1P8);
/* delay 1ms for realtek's power sequence request */
mdelay(1);
/* vcama set to 1.8V */
mt6391_configure_ldo(LDO_VCAMA, LDO_1P8);
/* reset ALC5676 */
if (board_id() + CONFIG_BOARD_ID_ADJUSTMENT < 5)
gpio_output(GPIO(LCM_RST), 1);
/* SoC I2S */
gpio_set_mode(GPIO(I2S0_LRCK), PAD_I2S0_LRCK_FUNC_I2S1_WS);
gpio_set_mode(GPIO(I2S0_BCK), PAD_I2S0_BCK_FUNC_I2S1_BCK);
gpio_set_mode(GPIO(I2S0_MCK), PAD_I2S0_MCK_FUNC_I2S1_MCK);
gpio_set_mode(GPIO(I2S0_DATA0), PAD_I2S0_DATA0_FUNC_I2S1_DO_1);
gpio_set_mode(GPIO(I2S0_DATA1), PAD_I2S0_DATA1_FUNC_I2S2_DI_2);
/* codec ext MCLK ON */
mt6391_gpio_output(MT6391_KP_COL4, 1);
switch (board_id() + CONFIG_BOARD_ID_ADJUSTMENT) {
case 2:
case 3:
case 4:
mt6391_gpio_output(MT6391_KP_COL5, 1);
break;
case 5:
case 6:
gpio_set_mode(GPIO(UCTS0), PAD_UCTS0_FUNC_I2S2_DI_1);
mt6391_gpio_output(MT6391_KP_COL5, 1);
break;
default:
break;
}
/* Init i2c bus Timing register for audio codecs */
mtk_i2c_bus_init(CODEC_I2C_BUS);
/* set I2S clock to 48KHz */
mt_pll_set_aud_div(48 * KHz);
}
static void configure_usb(void)
{
setup_usb_host();
if (board_id() + CONFIG_BOARD_ID_ADJUSTMENT > 3) {
/* Type C port 0 Over current alert pin */
gpio_input_pullup(GPIO(MSDC3_DSL));
/* Enable USB3 type A port 0 5V load switch */
gpio_output(GPIO(CM2MCLK), 1);
/* USB3 Type A port 0 power over current alert pin */
gpio_input_pullup(GPIO(CMPCLK));
/* Type C port 1 over current alert pin */
if (board_id() + CONFIG_BOARD_ID_ADJUSTMENT < 7)
gpio_input_pullup(GPIO(PCM_SYNC));
}
if (board_id() + CONFIG_BOARD_ID_ADJUSTMENT > 4 &&
board_id() + CONFIG_BOARD_ID_ADJUSTMENT < 7)
{
/* USB 2.0 type A port over current interrupt pin(low active) */
gpio_input_pullup(GPIO(UCTS2));
/* USB 2.0 type A port BC1.2 STATUS(low active) */
gpio_input_pullup(GPIO(AUD_DAT_MISO));
}
}
static void configure_usb_hub(void)
{
/* set USB hub reset pin (low active) to high */
if (board_id() + CONFIG_BOARD_ID_ADJUSTMENT > 4)
gpio_output(GPIO(UTXD3), 1);
}
/* Setup backlight control pins as output pin and power-off by default */
static void configure_backlight(void)
{
/* Configure PANEL_LCD_POWER_EN */
switch (board_id() + CONFIG_BOARD_ID_ADJUSTMENT) {
case 3:
gpio_output(GPIO(UCTS2), 0);
break;
case 4:
gpio_output(GPIO(SRCLKENAI), 0);
break;
default:
gpio_output(GPIO(UTXD2), 0);
break;
}
gpio_output(GPIO(DISP_PWM0), 0); /* DISP_PWM0 */
gpio_output(GPIO(PCM_TX), 0); /* PANEL_POWER_EN */
}
static void configure_display(void)
{
/* board from Rev2 */
gpio_output(GPIO(CMMCLK), 1); /* PANEL_3V3_ENABLE */
/* vgp2 set to 3.3V for ps8640 */
mt6391_configure_ldo(LDO_VGP2, LDO_3P3);
gpio_output(GPIO(URTS0), 0); /* PS8640_SYSRSTN */
/* PS8640_1V2_ENABLE */
if (board_id() + CONFIG_BOARD_ID_ADJUSTMENT == 4)
gpio_output(GPIO(SRCLKENAI2), 1);
else
gpio_output(GPIO(URTS2), 1);
/* delay 2ms for vgp2 and PS8640_1V2_ENABLE stable */
mdelay(2);
/* PS8640_PDN */
if (board_id() + CONFIG_BOARD_ID_ADJUSTMENT > 4)
gpio_output(GPIO(LCM_RST), 1);
else
gpio_output(GPIO(UCTS0), 1);
gpio_output(GPIO(PCM_CLK), 1); /* PS8640_MODE_CONF */
gpio_output(GPIO(URTS0), 1); /* PS8640_SYSRSTN */
/* for level shift(1.8V to 3.3V) on */
udelay(100);
}
static int read_edid_from_ps8640(struct edid *edid)
{
u8 i2c_bus, i2c_addr;
if (board_id() + CONFIG_BOARD_ID_ADJUSTMENT > 6) {
i2c_bus = 0;
i2c_addr = 0x8;
} else {
i2c_bus = 4;
i2c_addr = 0x18;
}
mtk_i2c_bus_init(i2c_bus);
ps8640_init(i2c_bus, i2c_addr);
if (ps8640_get_edid(i2c_bus, i2c_addr, edid)) {
printk(BIOS_ERR, "Can't get panel's edid\n");
return -1;
}
return 0;
}
static void display_startup(void)
{
struct edid edid;
int ret;
u32 mipi_dsi_flags;
if (read_edid_from_ps8640(&edid) < 0)
return;
mipi_dsi_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
edid_set_framebuffer_bits_per_pixel(&edid, 32, 0);
mtk_ddp_init();
ret = mtk_dsi_init(mipi_dsi_flags, MIPI_DSI_FMT_RGB888, 4, &edid, NULL);
if (ret < 0) {
printk(BIOS_ERR, "dsi init fail\n");
return;
}
mtk_ddp_mode_set(&edid);
fb_new_framebuffer_info_from_edid(&edid, (uintptr_t)0);
}
static void mainboard_init(struct device *dev)
{
/* TP_SHIFT_EN: Enables the level shifter for I2C bus 4 (TPAD), which
* also contains the PS8640 eDP bridge and the USB hub.
*/
if (board_id() + CONFIG_BOARD_ID_ADJUSTMENT < 5)
mt6391_gpio_output(MT6391_KP_ROW2, 1);
/* Config SD card detection pin */
gpio_input_pullup(GPIO(EINT1)); /* SD_DET */
configure_audio();
/* fix dsi lp mode is half voltage attenuation */
mtk_dsi_pin_drv_ctrl();
if (display_init_required()) {
mtcmos_display_power_on();
configure_backlight();
configure_display();
display_startup();
} else {
printk(BIOS_INFO, "Skipping display init.\n");
}
configure_usb();
configure_usb_hub();
configure_ext_buck();
configure_touchscreen();
}
static void mainboard_enable(struct device *dev)
{
dev->ops->init = &mainboard_init;
}
struct chip_operations mainboard_ops = {
.enable_dev = mainboard_enable,
};