aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mainboard/google/oak/mainboard.c7
-rw-r--r--src/soc/mediatek/mt8173/ddp.c66
-rw-r--r--src/soc/mediatek/mt8173/dsi.c222
-rw-r--r--src/soc/mediatek/mt8173/include/soc/addressmap.h1
-rw-r--r--src/soc/mediatek/mt8173/include/soc/ddp.h27
-rw-r--r--src/soc/mediatek/mt8173/include/soc/dsi.h162
6 files changed, 418 insertions, 67 deletions
diff --git a/src/mainboard/google/oak/mainboard.c b/src/mainboard/google/oak/mainboard.c
index 2e17678cb1..4320f6ec1c 100644
--- a/src/mainboard/google/oak/mainboard.c
+++ b/src/mainboard/google/oak/mainboard.c
@@ -212,6 +212,7 @@ static void display_startup(void)
struct edid edid;
u8 i2c_bus, i2c_addr;
int ret;
+ bool dual_dsi_mode = false;
if (board_id() + CONFIG_BOARD_ID_ADJUSTMENT > 6) {
i2c_bus = 0;
@@ -231,15 +232,15 @@ static void display_startup(void)
edid_set_framebuffer_bits_per_pixel(&edid, 32, 0);
- mtk_ddp_init();
+ mtk_ddp_init(dual_dsi_mode);
ret = mtk_dsi_init(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
- MIPI_DSI_FMT_RGB888, 4, &edid);
+ MIPI_DSI_FMT_RGB888, 4, dual_dsi_mode, &edid);
if (ret < 0) {
printk(BIOS_ERR, "dsi init fail\n");
return;
}
- mtk_ddp_mode_set(&edid);
+ mtk_ddp_mode_set(&edid, dual_dsi_mode);
set_vbe_mode_info_valid(&edid, (uintptr_t)0);
}
diff --git a/src/soc/mediatek/mt8173/ddp.c b/src/soc/mediatek/mt8173/ddp.c
index b7a8a6b670..977a9e5fe8 100644
--- a/src/soc/mediatek/mt8173/ddp.c
+++ b/src/soc/mediatek/mt8173/ddp.c
@@ -26,15 +26,22 @@
#define RDMA_FIFO_PSEUDO_SIZE(bytes) (((bytes) / 16) << 16)
#define RDMA_OUTPUT_VALID_FIFO_THRESHOLD(bytes) ((bytes) / 16)
-static void disp_config_main_path_connection(void)
+static void disp_config_main_path_connection(bool dual_dsi_mode)
{
write32(&mmsys_cfg->disp_ovl0_mout_en, OVL0_MOUT_EN_COLOR0);
- write32(&mmsys_cfg->disp_od_mout_en, OD_MOUT_EN_RDMA0);
+ write32(&mmsys_cfg->disp_color0_sel_in, COLOR0_SEL_IN_OVL0);
- write32(&mmsys_cfg->disp_ufoe_mout_en, UFOE_MOUT_EN_DSI0);
+ write32(&mmsys_cfg->disp_od_mout_en, OD_MOUT_EN_RDMA0);
- write32(&mmsys_cfg->disp_color0_sel_in, COLOR0_SEL_IN_OVL0);
+ if (dual_dsi_mode) {
+ write32(&mmsys_cfg->disp_ufoe_mout_en, UFOE_MOUT_EN_SPLIT1);
+ write32(&mmsys_cfg->dsi0_sel_in, DSI0_SEL_IN_SPLIT1);
+ write32(&mmsys_cfg->dsi1_sel_in, DSI1_SEL_IN_SPLIT1);
+ } else {
+ write32(&mmsys_cfg->disp_ufoe_mout_en, UFOE_MOUT_EN_DSI0);
+ write32(&mmsys_cfg->dsi0_sel_in, DSI0_SEL_IN_UFOE);
+ }
}
static void disp_config_main_path_mutex(void)
@@ -100,9 +107,15 @@ static void od_start(u32 width, u32 height)
write32(&disp_od->en, 1);
}
-static void ufoe_start(void)
+static void ufoe_start(u32 width, u32 height, bool dual_dsi_mode)
{
- write32(&disp_ufoe->start, UFO_BYPASS);
+ if (dual_dsi_mode) {
+ write32(&disp_ufoe->frame_width, width);
+ write32(&disp_ufoe->frame_height, height);
+ write32(&disp_ufoe->start, UFO_LR);
+ } else {
+ write32(&disp_ufoe->start, UFO_BYPASS);
+ }
}
static void color_start(u32 width, u32 height)
@@ -113,6 +126,11 @@ static void color_start(u32 width, u32 height)
write32(&disp_color[0]->start, BIT(0));
}
+static void split_start(void)
+{
+ write32(&disp_split->start, 1);
+}
+
static void ovl_layer_config(u32 fmt, u32 bpp, u32 width, u32 height)
{
write32(&disp_ovl[0]->layer[0].con, fmt << 12);
@@ -122,7 +140,8 @@ static void ovl_layer_config(u32 fmt, u32 bpp, u32 width, u32 height)
ovl_layer_enable();
}
-static void main_disp_path_setup(u32 width, u32 height, u32 pixel_clk)
+static void main_disp_path_setup(u32 width, u32 height, u32 pixel_clk,
+ bool dual_dsi_mode)
{
/* Setup OVL */
ovl_set_roi(width, height, 0);
@@ -134,44 +153,61 @@ static void main_disp_path_setup(u32 width, u32 height, u32 pixel_clk)
od_start(width, height);
/* Setup UFOE */
- ufoe_start();
+ ufoe_start(width, height, dual_dsi_mode);
+
+ if (dual_dsi_mode)
+ split_start();
/* Setup Color */
color_start(width, height);
/* Setup main path connection */
- disp_config_main_path_connection();
+ disp_config_main_path_connection(dual_dsi_mode);
/* Setup main path mutex */
disp_config_main_path_mutex();
}
-static void disp_clock_on(void)
+static void disp_clock_on(bool dual_dsi_mode)
{
+ u32 dual_dsi_cg_con0;
+ u32 dual_dsi_cg_con1;
+
+ if (dual_dsi_mode) {
+ dual_dsi_cg_con0 = CG_CON0_DISP_SPLIT1;
+ dual_dsi_cg_con1 = CG_CON1_DSI1_ENGINE | CG_CON1_DSI1_DIGITAL;
+ } else {
+ dual_dsi_cg_con0 = 0;
+ dual_dsi_cg_con1 = 0;
+ }
+
clrbits_le32(&mmsys_cfg->mmsys_cg_con0, CG_CON0_SMI_COMMON |
CG_CON0_SMI_LARB0 |
CG_CON0_MUTEX_32K |
CG_CON0_DISP_OVL0 |
CG_CON0_DISP_RDMA0 |
CG_CON0_DISP_COLOR0 |
+ CG_CON0_DISP_UFOE |
+ dual_dsi_cg_con0 |
CG_CON0_DISP_OD);
clrbits_le32(&mmsys_cfg->mmsys_cg_con1, CG_CON1_DSI0_ENGINE |
- CG_CON1_DSI0_DIGITAL);
+ CG_CON1_DSI0_DIGITAL |
+ dual_dsi_cg_con1);
}
-void mtk_ddp_init(void)
+void mtk_ddp_init(bool dual_dsi_mode)
{
- disp_clock_on();
+ disp_clock_on(dual_dsi_mode);
}
-void mtk_ddp_mode_set(const struct edid *edid)
+void mtk_ddp_mode_set(const struct edid *edid, bool dual_dsi_mode)
{
u32 fmt = OVL_INFMT_RGBA8888;
u32 bpp = edid->framebuffer_bits_per_pixel / 8;
main_disp_path_setup(edid->mode.ha, edid->mode.va,
- edid->mode.pixel_clock);
+ edid->mode.pixel_clock, dual_dsi_mode);
rdma_start();
diff --git a/src/soc/mediatek/mt8173/dsi.c b/src/soc/mediatek/mt8173/dsi.c
index 3500bf1d01..b445d6c6ea 100644
--- a/src/soc/mediatek/mt8173/dsi.c
+++ b/src/soc/mediatek/mt8173/dsi.c
@@ -20,8 +20,75 @@
#include <soc/i2c.h>
#include <soc/gpio.h>
#include <soc/dsi.h>
+#include <soc/ddp.h>
#include <timer.h>
+static bool dual_dsi_mode;
+
+static void mipi_write32(void *a, uint32_t v)
+{
+ void *a1 = a + (MIPI_TX1_BASE - MIPI_TX0_BASE);
+ write32(a, v);
+ if (dual_dsi_mode)
+ write32(a1, v);
+}
+
+static void mipi_clrsetbits_le32(void *a, uint32_t m, uint32_t v)
+{
+ void *a1 = a + (MIPI_TX1_BASE - MIPI_TX0_BASE);
+ clrsetbits_le32(a, m, v);
+ if (dual_dsi_mode)
+ clrsetbits_le32(a1, m, v);
+}
+
+static void mipi_clrbits_le32(void *a, uint32_t m)
+{
+ void *a1 = a + (MIPI_TX1_BASE - MIPI_TX0_BASE);
+ clrbits_le32(a, m);
+ if (dual_dsi_mode)
+ clrbits_le32(a1, m);
+}
+
+static void mipi_setbits_le32(void *a, uint32_t m)
+{
+ void *a1 = a + (MIPI_TX1_BASE - MIPI_TX0_BASE);
+ setbits_le32(a, m);
+ if (dual_dsi_mode)
+ setbits_le32(a1, m);
+}
+
+static void dsi_write32(void *a, uint32_t v)
+{
+ void *a1 = a + (DSI1_BASE - DSI0_BASE);
+ write32(a, v);
+ if (dual_dsi_mode)
+ write32(a1, v);
+}
+
+static void dsi_clrsetbits_le32(void *a, uint32_t m, uint32_t v)
+{
+ void *a1 = a + (DSI1_BASE - DSI0_BASE);
+ clrsetbits_le32(a, m, v);
+ if (dual_dsi_mode)
+ clrsetbits_le32(a1, m, v);
+}
+
+static void dsi_clrbits_le32(void *a, uint32_t m)
+{
+ void *a1 = a + (DSI1_BASE - DSI0_BASE);
+ clrbits_le32(a, m);
+ if (dual_dsi_mode)
+ clrbits_le32(a1, m);
+}
+
+static void dsi_setbits_le32(void *a, uint32_t m)
+{
+ void *a1 = a + (DSI1_BASE - DSI0_BASE);
+ setbits_le32(a, m);
+ if (dual_dsi_mode)
+ setbits_le32(a1, m);
+}
+
static int mtk_dsi_phy_clk_setting(u32 format, u32 lanes,
const struct edid *edid)
{
@@ -29,7 +96,7 @@ static int mtk_dsi_phy_clk_setting(u32 format, u32 lanes,
u64 pcw;
u32 reg;
u32 bit_per_pixel;
- int i, data_rate;
+ int i, data_rate, mipi_tx_rate;
reg = read32(&mipi_tx0->dsi_bg_con);
@@ -41,19 +108,19 @@ static int mtk_dsi_phy_clk_setting(u32 format, u32 lanes,
reg = (reg & (~RG_DSI_V12_SEL)) | (4 << 5);
reg |= RG_DSI_BG_CKEN;
reg |= RG_DSI_BG_CORE_EN;
- write32(&mipi_tx0->dsi_bg_con, reg);
+ mipi_write32(&mipi_tx0->dsi_bg_con, reg);
udelay(30);
- clrsetbits_le32(&mipi_tx0->dsi_top_con, RG_DSI_LNT_IMP_CAL_CODE,
+ mipi_clrsetbits_le32(&mipi_tx0->dsi_top_con, RG_DSI_LNT_IMP_CAL_CODE,
8 << 4 | RG_DSI_LNT_HS_BIAS_EN);
- setbits_le32(&mipi_tx0->dsi_con,
+ mipi_setbits_le32(&mipi_tx0->dsi_con,
RG_DSI0_CKG_LDOOUT_EN | RG_DSI0_LDOCORE_EN);
- clrsetbits_le32(&mipi_tx0->dsi_pll_pwr, RG_DSI_MPPLL_SDM_ISO_EN,
+ mipi_clrsetbits_le32(&mipi_tx0->dsi_pll_pwr, RG_DSI_MPPLL_SDM_ISO_EN,
RG_DSI_MPPLL_SDM_PWR_ON);
- clrbits_le32(&mipi_tx0->dsi_pll_con0, RG_DSI0_MPPLL_PLL_EN);
+ mipi_clrbits_le32(&mipi_tx0->dsi_pll_con0, RG_DSI0_MPPLL_PLL_EN);
switch (format) {
case MIPI_DSI_FMT_RGB565:
@@ -78,6 +145,10 @@ static int mtk_dsi_phy_clk_setting(u32 format, u32 lanes,
*/
data_rate = edid->mode.pixel_clock * 102 * bit_per_pixel /
(lanes * 1000 * 100);
+ mipi_tx_rate = data_rate;
+ if (dual_dsi_mode)
+ data_rate /= 2;
+
if (data_rate > 500) {
txdiv0 = 0;
txdiv1 = 0;
@@ -100,7 +171,7 @@ static int mtk_dsi_phy_clk_setting(u32 format, u32 lanes,
return -1;
}
- clrsetbits_le32(&mipi_tx0->dsi_pll_con0,
+ mipi_clrsetbits_le32(&mipi_tx0->dsi_pll_con0,
RG_DSI0_MPPLL_TXDIV1 | RG_DSI0_MPPLL_TXDIV0 |
RG_DSI0_MPPLL_PREDIV, txdiv1 << 5 | txdiv0 << 3);
@@ -114,23 +185,23 @@ static int mtk_dsi_phy_clk_setting(u32 format, u32 lanes,
*/
pcw = (u64)(data_rate * (1 << txdiv0) * (1 << txdiv1)) << 24;
pcw /= 13;
- write32(&mipi_tx0->dsi_pll_con2, pcw);
+ mipi_write32(&mipi_tx0->dsi_pll_con2, pcw);
- setbits_le32(&mipi_tx0->dsi_pll_con1, RG_DSI0_MPPLL_SDM_FRA_EN);
+ mipi_setbits_le32(&mipi_tx0->dsi_pll_con1, RG_DSI0_MPPLL_SDM_FRA_EN);
- setbits_le32(&mipi_tx0->dsi_clock_lane, LDOOUT_EN);
+ mipi_setbits_le32(&mipi_tx0->dsi_clock_lane, LDOOUT_EN);
for (i = 0; i < lanes; i++)
- setbits_le32(&mipi_tx0->dsi_data_lane[i], LDOOUT_EN);
+ mipi_setbits_le32(&mipi_tx0->dsi_data_lane[i], LDOOUT_EN);
- setbits_le32(&mipi_tx0->dsi_pll_con0, RG_DSI0_MPPLL_PLL_EN);
+ mipi_setbits_le32(&mipi_tx0->dsi_pll_con0, RG_DSI0_MPPLL_PLL_EN);
udelay(40);
- clrbits_le32(&mipi_tx0->dsi_pll_con1, RG_DSI0_MPPLL_SDM_SSC_EN);
- clrbits_le32(&mipi_tx0->dsi_top_con, RG_DSI_PAD_TIE_LOW_EN);
+ mipi_clrbits_le32(&mipi_tx0->dsi_pll_con1, RG_DSI0_MPPLL_SDM_SSC_EN);
+ mipi_clrbits_le32(&mipi_tx0->dsi_top_con, RG_DSI_PAD_TIE_LOW_EN);
- return data_rate;
+ return mipi_tx_rate;
}
static void mtk_dsi_phy_timconfig(u32 data_rate)
@@ -151,26 +222,26 @@ static void mtk_dsi_phy_timconfig(u32 data_rate)
div_round_up(80 + 52 * ui, cycle_time) << 8 |
div_round_up(0x40, cycle_time);
- write32(&dsi0->dsi_phy_timecon0, timcon0);
- write32(&dsi0->dsi_phy_timecon1, timcon1);
- write32(&dsi0->dsi_phy_timecon2, timcon2);
- write32(&dsi0->dsi_phy_timecon3, timcon3);
+ dsi_write32(&dsi0->dsi_phy_timecon0, timcon0);
+ dsi_write32(&dsi0->dsi_phy_timecon1, timcon1);
+ dsi_write32(&dsi0->dsi_phy_timecon2, timcon2);
+ dsi_write32(&dsi0->dsi_phy_timecon3, timcon3);
}
static void mtk_dsi_reset(void)
{
- setbits_le32(&dsi0->dsi_con_ctrl, 3);
- clrbits_le32(&dsi0->dsi_con_ctrl, 1);
+ dsi_setbits_le32(&dsi0->dsi_con_ctrl, 3);
+ dsi_clrbits_le32(&dsi0->dsi_con_ctrl, 1);
}
static void mtk_dsi_clk_hs_mode_enable(void)
{
- setbits_le32(&dsi0->dsi_phy_lccon, LC_HS_TX_EN);
+ dsi_setbits_le32(&dsi0->dsi_phy_lccon, LC_HS_TX_EN);
}
static void mtk_dsi_clk_hs_mode_disable(void)
{
- clrbits_le32(&dsi0->dsi_phy_lccon, LC_HS_TX_EN);
+ dsi_clrbits_le32(&dsi0->dsi_phy_lccon, LC_HS_TX_EN);
}
static void mtk_dsi_set_mode(u32 mode_flags)
@@ -187,10 +258,10 @@ static void mtk_dsi_set_mode(u32 mode_flags)
tmp_reg1 = SYNC_PULSE_MODE;
}
- write32(&dsi0->dsi_mode_ctrl, tmp_reg1);
+ dsi_write32(&dsi0->dsi_mode_ctrl, tmp_reg1);
}
-static void mtk_dsi_rxtx_control(u32 lanes)
+static void mtk_dsi_rxtx_control(u32 mode_flags, u32 lanes)
{
u32 tmp_reg = 0;
@@ -210,7 +281,10 @@ static void mtk_dsi_rxtx_control(u32 lanes)
break;
}
- write32(&dsi0->dsi_txrx_ctrl, tmp_reg);
+ tmp_reg |= (mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) << 6;
+ tmp_reg |= (mode_flags & MIPI_DSI_MODE_EOT_PACKET) >> 3;
+
+ dsi_write32(&dsi0->dsi_txrx_ctrl, tmp_reg);
}
static void mtk_dsi_config_vdo_timing(u32 mode_flags, u32 format,
@@ -223,6 +297,7 @@ static void mtk_dsi_config_vdo_timing(u32 mode_flags, u32 format,
u32 vfp_byte;
u32 bpp;
u32 packet_fmt;
+ u32 hactive;
if (format == MIPI_DSI_FMT_RGB565)
bpp = 2;
@@ -233,10 +308,10 @@ static void mtk_dsi_config_vdo_timing(u32 mode_flags, u32 format,
edid->mode.vborder;
vfp_byte = edid->mode.vso - edid->mode.vborder;
- write32(&dsi0->dsi_vsa_nl, edid->mode.vspw);
- write32(&dsi0->dsi_vbp_nl, vbp_byte);
- write32(&dsi0->dsi_vfp_nl, vfp_byte);
- write32(&dsi0->dsi_vact_nl, edid->mode.va);
+ dsi_write32(&dsi0->dsi_vsa_nl, edid->mode.vspw);
+ dsi_write32(&dsi0->dsi_vbp_nl, vbp_byte);
+ dsi_write32(&dsi0->dsi_vfp_nl, vfp_byte);
+ dsi_write32(&dsi0->dsi_vact_nl, edid->mode.va);
if (mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
hbp_byte = (edid->mode.hbl - edid->mode.hso - edid->mode.hspw -
@@ -248,9 +323,9 @@ static void mtk_dsi_config_vdo_timing(u32 mode_flags, u32 format,
hsync_active_byte = edid->mode.hspw * bpp - 10;
hfp_byte = (edid->mode.hso - edid->mode.hborder) * bpp - 12;
- write32(&dsi0->dsi_hsa_wc, hsync_active_byte);
- write32(&dsi0->dsi_hbp_wc, hbp_byte);
- write32(&dsi0->dsi_hfp_wc, hfp_byte);
+ dsi_write32(&dsi0->dsi_hsa_wc, hsync_active_byte);
+ dsi_write32(&dsi0->dsi_hbp_wc, hbp_byte);
+ dsi_write32(&dsi0->dsi_hfp_wc, hfp_byte);
switch (format) {
case MIPI_DSI_FMT_RGB888:
@@ -270,31 +345,89 @@ static void mtk_dsi_config_vdo_timing(u32 mode_flags, u32 format,
break;
}
- packet_fmt |= edid->mode.ha * bpp & DSI_PS_WC;
- write32(&dsi0->dsi_psctrl, packet_fmt);
+ hactive = edid->mode.ha;
+ if (dual_dsi_mode)
+ hactive /= 2;
+ packet_fmt |= (hactive * bpp) & DSI_PS_WC;
+
+ dsi_write32(&dsi0->dsi_psctrl, packet_fmt);
}
static void mtk_dsi_start(void)
{
- write32(&dsi0->dsi_start, 0);
+ dsi_write32(&dsi0->dsi_start, 0);
+ /* Only start master DSI */
write32(&dsi0->dsi_start, 1);
}
-int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes,
+static void mtk_dsi_tx_cmd_type0(u8 cmd)
+{
+ struct stopwatch sw;
+ u32 cmdq0;
+ u32 intsta_0, intsta_1;
+
+ cmdq0 = (MIPI_DSI_DCS_SHORT_WRITE << 8) | SHORT_PACKET | (cmd << 16);
+
+ dsi_write32(&dsi0->dsi_cmdq0, cmdq0);
+ dsi_clrsetbits_le32(&dsi0->dsi_cmdq_size, CMDQ_SIZE, 1);
+ dsi_write32(&dsi0->dsi_intsta, 0);
+
+ dsi_write32(&dsi0->dsi_start, 1);
+
+ stopwatch_init_usecs_expire(&sw, 400);
+ do {
+ intsta_0 = read32(&dsi0->dsi_intsta);
+ intsta_1 = read32(&dsi1->dsi_intsta);
+ if ((intsta_0 & CMD_DONE_INT_FLAG) &&
+ (intsta_1 & CMD_DONE_INT_FLAG))
+ break;
+ udelay(4);
+ } while (!stopwatch_expired(&sw));
+
+ if (!(intsta_0 & CMD_DONE_INT_FLAG))
+ printk(BIOS_ERR, "DSI0 DONE INT Timeout\n");
+
+ if (!(intsta_1 & CMD_DONE_INT_FLAG))
+ printk(BIOS_ERR, "DSI1 DONE INT Timeout\n");
+
+ dsi_write32(&dsi0->dsi_start, 0);
+}
+
+int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, bool dual,
const struct edid *edid)
{
- int data_rate = mtk_dsi_phy_clk_setting(format, lanes, edid);
+ int data_rate;
+
+ dual_dsi_mode = dual;
+
+ data_rate = mtk_dsi_phy_clk_setting(format, lanes, edid);
if (data_rate < 0)
return -1;
mtk_dsi_reset();
mtk_dsi_phy_timconfig(data_rate);
- mtk_dsi_rxtx_control(lanes);
+ mtk_dsi_rxtx_control(mode_flags, lanes);
mtk_dsi_clk_hs_mode_disable();
mtk_dsi_config_vdo_timing(mode_flags, format, edid);
mtk_dsi_set_mode(mode_flags);
mtk_dsi_clk_hs_mode_enable();
+
+ if (dual_dsi_mode) {
+ dsi_write32(&dsi0->dsi_start, 0);
+ /* Disable dual_dsi when in CMD_MODE */
+ dsi_write32(&dsi0->dsi_con_ctrl, DSI_EN);
+
+ dsi_write32(&dsi0->dsi_mode_ctrl, CMD_MODE);
+
+ mtk_dsi_tx_cmd_type0(MIPI_DCS_EXIT_SLEEP_MODE);
+ mtk_dsi_tx_cmd_type0(MIPI_DCS_SET_DISPLAY_ON);
+
+ dsi_write32(&dsi0->dsi_con_ctrl, DSI_EN | DSI_DUAL);
+
+ dsi_write32(&dsi0->dsi_mode_ctrl, BURST_MODE);
+ }
+
mtk_dsi_start();
return 0;
@@ -303,8 +436,9 @@ int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes,
void mtk_dsi_pin_drv_ctrl(void)
{
struct stopwatch sw;
+ uint32_t pwr_ack;
- setbits_le32(&lvds_tx1->vopll_ctl3, RG_DA_LVDSTX_PWR_ON);
+ mipi_setbits_le32(&lvds_tx1->vopll_ctl3, RG_DA_LVDSTX_PWR_ON);
stopwatch_init_usecs_expire(&sw, 1000);
@@ -313,7 +447,11 @@ void mtk_dsi_pin_drv_ctrl(void)
printk(BIOS_ERR, "enable lvdstx_power failed!!!\n");
return;
}
- } while ((read32(&lvds_tx1->vopll_ctl3) & RG_AD_LVDSTX_PWR_ACK) == 0);
+ pwr_ack = read32(&lvds_tx1->vopll_ctl3) & RG_AD_LVDSTX_PWR_ACK;
+ if (dual_dsi_mode)
+ pwr_ack &= read32(&lvds_tx2->vopll_ctl3) &
+ RG_AD_LVDSTX_PWR_ACK;
+ } while (pwr_ack == 0);
- clrbits_le32(&lvds_tx1->vopll_ctl3, RG_DA_LVDS_ISO_EN);
+ mipi_clrbits_le32(&lvds_tx1->vopll_ctl3, RG_DA_LVDS_ISO_EN);
}
diff --git a/src/soc/mediatek/mt8173/include/soc/addressmap.h b/src/soc/mediatek/mt8173/include/soc/addressmap.h
index cab127be75..cc1b39d67c 100644
--- a/src/soc/mediatek/mt8173/include/soc/addressmap.h
+++ b/src/soc/mediatek/mt8173/include/soc/addressmap.h
@@ -64,6 +64,7 @@ enum {
DISP_RDMA2_BASE = IO_PHYS + 0x4010000,
DISP_COLOR0_BASE = IO_PHYS + 0x4013000,
DISP_COLOR1_BASE = IO_PHYS + 0x4014000,
+ DISP_SPLIT1_BASE = IO_PHYS + 0x4019000,
DISP_UFOE_BASE = IO_PHYS + 0x401A000,
DSI0_BASE = IO_PHYS + 0x401B000,
DSI1_BASE = IO_PHYS + 0x401C000,
diff --git a/src/soc/mediatek/mt8173/include/soc/ddp.h b/src/soc/mediatek/mt8173/include/soc/ddp.h
index 9846b1ad40..20e356a909 100644
--- a/src/soc/mediatek/mt8173/include/soc/ddp.h
+++ b/src/soc/mediatek/mt8173/include/soc/ddp.h
@@ -140,6 +140,7 @@ struct mmsys_cfg_regs {
u32 hdmi_en;
};
+check_member(mmsys_cfg_regs, mmsys_sw1_rst_b, 0x144);
check_member(mmsys_cfg_regs, hdmi_en, 0x904);
static struct mmsys_cfg_regs * const mmsys_cfg = (void *) MMSYS_BASE;
@@ -206,7 +207,20 @@ enum {
OVL0_MOUT_EN_COLOR0 = BIT(0),
OD_MOUT_EN_RDMA0 = BIT(0),
UFOE_MOUT_EN_DSI0 = BIT(0),
- COLOR0_SEL_IN_OVL0 = BIT(0),
+ UFOE_MOUT_EN_SPLIT1 = BIT(1),
+};
+
+enum {
+ COLOR0_SEL_IN_OVL0 = 1,
+ DSI0_SEL_IN_UFOE = 0,
+ DSI0_SEL_IN_SPLIT1 = 1,
+ DSI1_SEL_IN_SPLIT1 = 0,
+};
+
+/* MMSYS_SW1_RST_B */
+enum {
+ MMSYS_SW1_RST_DSI0_B = BIT(2),
+ MMSYS_SW1_RST_DSI1_B = BIT(3),
};
struct disp_mutex_regs {
@@ -386,8 +400,15 @@ static struct disp_ufoe_regs * const disp_ufoe = (void *)DISP_UFOE_BASE;
enum {
UFO_BYPASS = BIT(2),
+ UFO_LR = BIT(3) | BIT(0),
};
+struct disp_split_regs {
+ u32 start;
+};
+
+static struct disp_split_regs * const disp_split = (void *)DISP_SPLIT1_BASE;
+
struct disp_color_regs {
u8 reserved0[1024];
u32 cfg_main;
@@ -426,7 +447,7 @@ enum OVL_INPUT_FORMAT {
OVL_INFMT_ABGR8888 = OVL_INFMT_ARGB8888 + OVL_COLOR_BASE,
};
-void mtk_ddp_init(void);
-void mtk_ddp_mode_set(const struct edid *edid);
+void mtk_ddp_init(bool dual_dsi_mode);
+void mtk_ddp_mode_set(const struct edid *edid, bool dual_dsi_mode);
#endif
diff --git a/src/soc/mediatek/mt8173/include/soc/dsi.h b/src/soc/mediatek/mt8173/include/soc/dsi.h
index 73f4425684..68f45d1144 100644
--- a/src/soc/mediatek/mt8173/include/soc/dsi.h
+++ b/src/soc/mediatek/mt8173/include/soc/dsi.h
@@ -71,21 +71,45 @@ struct dsi_regs {
u32 dsi_hbp_wc;
u32 dsi_hfp_wc;
u32 dsi_bllp_wc;
- u8 reserved2[4];
+ u32 dsi_cmdq_size;
u32 dsi_hstx_cklp_wc;
- u8 reserved3[156];
+ u8 reserved2[156];
u32 dsi_phy_lccon;
u32 dsi_phy_ld0con;
- u8 reserved4[4];
+ u8 reserved3[4];
u32 dsi_phy_timecon0;
u32 dsi_phy_timecon1;
u32 dsi_phy_timecon2;
u32 dsi_phy_timecon3;
+ u8 reserved4[16];
+ u32 dsi_vm_cmd_con;
+ u8 reserved5[204];
+ u32 dsi_cmdq0;
};
check_member(dsi_regs, dsi_phy_lccon, 0x104);
check_member(dsi_regs, dsi_phy_timecon3, 0x11c);
+check_member(dsi_regs, dsi_vm_cmd_con, 0x130);
+check_member(dsi_regs, dsi_cmdq0, 0x200);
static struct dsi_regs * const dsi0 = (void *)DSI0_BASE;
+static struct dsi_regs * const dsi1 = (void *)DSI1_BASE;
+
+/* DSI_INTSTA */
+enum {
+ LPRX_RD_RDY_INT_FLAG = BIT(0),
+ CMD_DONE_INT_FLAG = BIT(1),
+ TE_RDY_INT_FLAG = BIT(2),
+ VM_DONE_INT_FLAG = BIT(3),
+ EXT_TE_RDY_INT_FLAG = BIT(4),
+ DSI_BUSY = BIT(31),
+};
+
+/* DSI_CON_CTRL */
+enum {
+ DSI_RESET = BIT(0),
+ DSI_EN = BIT(1),
+ DSI_DUAL = BIT(4),
+};
/* DSI_MODE_CTRL */
enum {
@@ -108,6 +132,11 @@ enum {
PACKED_PS_24BIT_RGB888 = (3 << 16)
};
+/* DSI_CMDQ_SIZE */
+enum {
+ CMDQ_SIZE = 0x3f,
+};
+
/* DSI_PHY_LCCON */
enum {
LC_HS_TX_EN = BIT(0),
@@ -148,6 +177,23 @@ enum {
CLK_HS_EXIT = (0xf << 16)
};
+/* DSI_VM_CMD_CON */
+enum {
+ VM_CMD_EN = BIT(0),
+ TS_VFP_EN = BIT(5),
+};
+
+/* DSI_CMDQ0 */
+enum {
+ CONFIG = (0xff << 0),
+ SHORT_PACKET = 0,
+ LONG_PACKET = 2,
+ BTA = BIT(2),
+ DATA_ID = (0xff << 8),
+ DATA_0 = (0xff << 16),
+ DATA_1 = (0xff << 24),
+};
+
/* MIPITX_REG */
struct mipi_tx_regs {
u32 dsi_con;
@@ -182,6 +228,7 @@ check_member(mipi_tx_regs, dsi_top_con, 0x40);
check_member(mipi_tx_regs, dsi_pll_pwr, 0x68);
static struct mipi_tx_regs * const mipi_tx0 = (void *)MIPI_TX0_BASE;
+static struct mipi_tx_regs * const mipi_tx1 = (void *)MIPI_TX0_BASE;
/* MIPITX_DSI0_CON */
enum {
@@ -276,6 +323,7 @@ struct lvds_tx1_regs {
};
static struct lvds_tx1_regs * const lvds_tx1 = (void *)(MIPI_TX0_BASE + 0x800);
+static struct lvds_tx1_regs * const lvds_tx2 = (void *)(MIPI_TX1_BASE + 0x800);
/* LVDS_VOPLL_CTRL3 */
enum {
@@ -288,8 +336,114 @@ enum {
RG_DA_LVDSTX_PWR_ON = BIT(9)
};
+/* MIPI DSI Processor-to-Peripheral transaction types */
+enum {
+ MIPI_DSI_V_SYNC_START = 0x01,
+ MIPI_DSI_V_SYNC_END = 0x11,
+ MIPI_DSI_H_SYNC_START = 0x21,
+ MIPI_DSI_H_SYNC_END = 0x31,
+
+ MIPI_DSI_COLOR_MODE_OFF = 0x02,
+ MIPI_DSI_COLOR_MODE_ON = 0x12,
+ MIPI_DSI_SHUTDOWN_PERIPHERAL = 0x22,
+ MIPI_DSI_TURN_ON_PERIPHERAL = 0x32,
+
+ MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM = 0x03,
+ MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM = 0x13,
+ MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM = 0x23,
+
+ MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM = 0x04,
+ MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM = 0x14,
+ MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM = 0x24,
+
+ MIPI_DSI_DCS_SHORT_WRITE = 0x05,
+ MIPI_DSI_DCS_SHORT_WRITE_PARAM = 0x15,
+
+ MIPI_DSI_DCS_READ = 0x06,
+
+ MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE = 0x37,
+
+ MIPI_DSI_END_OF_TRANSMISSION = 0x08,
+
+ MIPI_DSI_NULL_PACKET = 0x09,
+ MIPI_DSI_BLANKING_PACKET = 0x19,
+ MIPI_DSI_GENERIC_LONG_WRITE = 0x29,
+ MIPI_DSI_DCS_LONG_WRITE = 0x39,
+
+ MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20 = 0x0c,
+ MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24 = 0x1c,
+ MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16 = 0x2c,
+
+ MIPI_DSI_PACKED_PIXEL_STREAM_30 = 0x0d,
+ MIPI_DSI_PACKED_PIXEL_STREAM_36 = 0x1d,
+ MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12 = 0x3d,
+
+ MIPI_DSI_PACKED_PIXEL_STREAM_16 = 0x0e,
+ MIPI_DSI_PACKED_PIXEL_STREAM_18 = 0x1e,
+ MIPI_DSI_PIXEL_STREAM_3BYTE_18 = 0x2e,
+ MIPI_DSI_PACKED_PIXEL_STREAM_24 = 0x3e,
+};
+
+/* MIPI DSI Peripheral-to-Processor transaction types */
+enum {
+ MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT = 0x02,
+ MIPI_DSI_RX_END_OF_TRANSMISSION = 0x08,
+ MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE = 0x11,
+ MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE = 0x12,
+ MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE = 0x1a,
+ MIPI_DSI_RX_DCS_LONG_READ_RESPONSE = 0x1c,
+ MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE = 0x21,
+ MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE = 0x22,
+};
+
+/* MIPI DCS commands */
+enum {
+ MIPI_DCS_NOP = 0x00,
+ MIPI_DCS_SOFT_RESET = 0x01,
+ MIPI_DCS_GET_DISPLAY_ID = 0x04,
+ MIPI_DCS_GET_RED_CHANNEL = 0x06,
+ MIPI_DCS_GET_GREEN_CHANNEL = 0x07,
+ MIPI_DCS_GET_BLUE_CHANNEL = 0x08,
+ MIPI_DCS_GET_DISPLAY_STATUS = 0x09,
+ MIPI_DCS_GET_POWER_MODE = 0x0A,
+ MIPI_DCS_GET_ADDRESS_MODE = 0x0B,
+ MIPI_DCS_GET_PIXEL_FORMAT = 0x0C,
+ MIPI_DCS_GET_DISPLAY_MODE = 0x0D,
+ MIPI_DCS_GET_SIGNAL_MODE = 0x0E,
+ MIPI_DCS_GET_DIAGNOSTIC_RESULT = 0x0F,
+ MIPI_DCS_ENTER_SLEEP_MODE = 0x10,
+ MIPI_DCS_EXIT_SLEEP_MODE = 0x11,
+ MIPI_DCS_ENTER_PARTIAL_MODE = 0x12,
+ MIPI_DCS_ENTER_NORMAL_MODE = 0x13,
+ MIPI_DCS_EXIT_INVERT_MODE = 0x20,
+ MIPI_DCS_ENTER_INVERT_MODE = 0x21,
+ MIPI_DCS_SET_GAMMA_CURVE = 0x26,
+ MIPI_DCS_SET_DISPLAY_OFF = 0x28,
+ MIPI_DCS_SET_DISPLAY_ON = 0x29,
+ MIPI_DCS_SET_COLUMN_ADDRESS = 0x2A,
+ MIPI_DCS_SET_PAGE_ADDRESS = 0x2B,
+ MIPI_DCS_WRITE_MEMORY_START = 0x2C,
+ MIPI_DCS_WRITE_LUT = 0x2D,
+ MIPI_DCS_READ_MEMORY_START = 0x2E,
+ MIPI_DCS_SET_PARTIAL_AREA = 0x30,
+ MIPI_DCS_SET_SCROLL_AREA = 0x33,
+ MIPI_DCS_SET_TEAR_OFF = 0x34,
+ MIPI_DCS_SET_TEAR_ON = 0x35,
+ MIPI_DCS_SET_ADDRESS_MODE = 0x36,
+ MIPI_DCS_SET_SCROLL_START = 0x37,
+ MIPI_DCS_EXIT_IDLE_MODE = 0x38,
+ MIPI_DCS_ENTER_IDLE_MODE = 0x39,
+ MIPI_DCS_SET_PIXEL_FORMAT = 0x3A,
+ MIPI_DCS_WRITE_MEMORY_CONTINUE = 0x3C,
+ MIPI_DCS_READ_MEMORY_CONTINUE = 0x3E,
+ MIPI_DCS_SET_TEAR_SCANLINE = 0x44,
+ MIPI_DCS_GET_SCANLINE = 0x45,
+ MIPI_DCS_READ_DDB_START = 0xA1,
+ MIPI_DCS_READ_DDB_CONTINUE = 0xA8,
+};
+
int mtk_dsi_init(u32 mode_flags, enum mipi_dsi_pixel_format format, u32 lanes,
- const struct edid *edid);
+ bool dual_dsi_mode, const struct edid *edid);
void mtk_dsi_pin_drv_ctrl(void);
#endif