Hung-Te Lin has uploaded this change for review.

View Change

soc/mediatek: dsi: Support sending MIPI init commands

For systems with real MIPI panels (8173/oak was using PS8640 eDP
bridge), we have to send DCS commands to initialize panel.

BUG=b:80501386,b:117254947
TEST=make -j # board = oak and boots

Change-Id: Ie7c824873465ac82a95bcb0ed67b8b9866987008
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
---
M src/mainboard/google/oak/mainboard.c
M src/soc/mediatek/common/dsi.c
M src/soc/mediatek/common/include/soc/dsi_common.h
M src/soc/mediatek/mt8173/include/soc/dsi.h
4 files changed, 150 insertions(+), 8 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/73/34773/1
diff --git a/src/mainboard/google/oak/mainboard.c b/src/mainboard/google/oak/mainboard.c
index 0dce17d..bac6fc5 100644
--- a/src/mainboard/google/oak/mainboard.c
+++ b/src/mainboard/google/oak/mainboard.c
@@ -234,7 +234,7 @@
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);
+ 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;
diff --git a/src/soc/mediatek/common/dsi.c b/src/soc/mediatek/common/dsi.c
index 17b127a..a269fe9 100644
--- a/src/soc/mediatek/common/dsi.c
+++ b/src/soc/mediatek/common/dsi.c
@@ -13,6 +13,7 @@
* GNU General Public License for more details.
*/

+#include <assert.h>
#include <device/mmio.h>
#include <console/console.h>
#include <device/mmio.h>
@@ -223,7 +224,134 @@
write32(&dsi0->dsi_start, 1);
}

-int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, const struct edid *edid)
+static bool mtk_dsi_is_read_command(u32 type)
+{
+ switch (type) {
+ case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
+ case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
+ case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
+ case MIPI_DSI_DCS_READ:
+ return true;
+ }
+ return false;
+}
+
+static void mtk_dsi_cmdq(u8 *data, u8 len, u32 type)
+{
+ struct stopwatch sw;
+ u8 *tx_buf = data;
+ u8 cmdq_size;
+ u32 reg_val, cmdq_mask, i, config, cmdq_off, intsta_0;
+
+ while (read32(&dsi0->dsi_intsta) & (1 << 31)) {
+ printk(BIOS_ERR, "%s wait dsi no busy\n", __func__);
+ mdelay(20);
+ }
+
+ write32(&dsi0->dsi_intsta, 0);
+
+ if (mtk_dsi_is_read_command(type))
+ config = BTA;
+ else
+ config = (len > 2) ? LONG_PACKET : SHORT_PACKET;
+
+ if (len > 2) {
+ cmdq_size = 1 + (len + 3) / 4;
+ cmdq_off = 4;
+ cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1;
+ reg_val = (len << 16) | (type << 8) | config;
+ } else {
+ cmdq_size = 1;
+ cmdq_off = 2;
+ cmdq_mask = CONFIG | DATA_ID;
+ reg_val = (type << 8) | config;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(dsi0->dsi_cmdq); i++)
+ write32(&dsi0->dsi_cmdq[i], 0);
+
+ u8 *cmdq0 = (u8 *)&dsi0->dsi_cmdq[0];
+ for (i = 0; i < len; i++) {
+ clrsetbits_le32(cmdq0 + ((cmdq_off + i) & (0xfffffffc)),
+ (0xff << (((i + cmdq_off) & 3) * 8)),
+ tx_buf[i] << (((i + cmdq_off) & 3) * 8));
+ }
+
+ clrsetbits_le32(&dsi0->dsi_cmdq[0], cmdq_mask, reg_val);
+ clrsetbits_le32(&dsi0->dsi_cmdq_size, CMDQ_SIZE, cmdq_size);
+ mtk_dsi_start();
+
+ stopwatch_init_usecs_expire(&sw, 400);
+ do {
+ intsta_0 = read32(&dsi0->dsi_intsta);
+ if (intsta_0 & CMD_DONE_INT_FLAG)
+ break;
+ udelay(4);
+ } while (!stopwatch_expired(&sw));
+
+ if (!(intsta_0 & CMD_DONE_INT_FLAG))
+ printk(BIOS_ERR, "dsi send cmd time-out(400uS)\n");
+}
+
+static void mtk_dsi_send_init_commands(struct lcm_init_table *init_cmd)
+{
+ assert(init_cmd);
+
+ for (; init_cmd->cmd != LCM_END_CMD; init_cmd++) {
+ u32 cmd = init_cmd->cmd, len = init_cmd->len;
+ u32 type;
+
+ switch (cmd) {
+ case LCM_DELAY_CMD:
+ mdelay(len);
+ continue;
+
+ case LCM_DCS_CMD:
+ switch (len) {
+ case 0:
+ return;
+ case 1:
+ type = MIPI_DSI_DCS_SHORT_WRITE;
+ break;
+ case 2:
+ type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
+ break;
+ default:
+ type = MIPI_DSI_DCS_LONG_WRITE;
+ break;
+ }
+ break;
+
+ case LCM_GENERIC_CMD:
+ switch (len) {
+ case 0:
+ type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
+ break;
+ case 1:
+ type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
+ break;
+ case 2:
+ type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
+ break;
+ default:
+ type = MIPI_DSI_GENERIC_LONG_WRITE;
+ break;
+ }
+ break;
+
+ default:
+ printk(BIOS_ERR, "%s: Unknown cmd: %d, abort\n",
+ __func__, cmd);
+ return;
+
+ }
+ assert(len <= sizeof(init_cmd->data));
+ mtk_dsi_cmdq(init_cmd->data, len, type);
+ }
+}
+
+int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes,
+ const struct edid *edid, struct lcm_init_table *init_cmd)
{
int data_rate;
u32 bpp = mtk_dsi_get_bits_per_pixel(format);
@@ -239,9 +367,10 @@
mtk_dsi_rxtx_control(mode_flags, lanes);
mtk_dsi_clk_hs_mode_disable();
mtk_dsi_config_vdo_timing(mode_flags, format, lanes, edid, &phy_timing);
- mtk_dsi_set_mode(mode_flags);
mtk_dsi_clk_hs_mode_enable();
-
+ if (init_cmd)
+ mtk_dsi_send_init_commands(init_cmd);
+ mtk_dsi_set_mode(mode_flags);
mtk_dsi_start();

return 0;
diff --git a/src/soc/mediatek/common/include/soc/dsi_common.h b/src/soc/mediatek/common/include/soc/dsi_common.h
index 3e72c58..8597b60 100644
--- a/src/soc/mediatek/common/include/soc/dsi_common.h
+++ b/src/soc/mediatek/common/include/soc/dsi_common.h
@@ -40,6 +40,18 @@
u8 clk_hs_exit;
};

+/* Definitions for cmd in lcm_init_table */
+#define LCM_END_CMD 0
+#define LCM_DELAY_CMD 1
+#define LCM_GENERIC_CMD 2
+#define LCM_DCS_CMD 3
+
+struct lcm_init_table {
+ u32 cmd;
+ u32 len;
+ u8 data[7];
+};
+
/* Functions that each SOC should provide. */
void mtk_dsi_reset(void);
/* mtk_dsi_phy_clk_setting should return the data rate in Mbps. */
@@ -49,7 +61,8 @@
void mtk_dsi_override_phy_timing(struct mtk_phy_timing *timing);

/* Public API provided in common/dsi.c */
-int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes,
- const struct edid *edid);
+int mtk_dsi_bpp_from_format(u32 format);
+int mtk_dsi_init(u32 mode_flags, u32 format, u32 lanes, const struct edid *edid,
+ struct lcm_init_table *init_cmd);

#endif // SOC_MEDIATEK_DSI_COMMON_H
diff --git a/src/soc/mediatek/mt8173/include/soc/dsi.h b/src/soc/mediatek/mt8173/include/soc/dsi.h
index e57bfc5..96d0aad 100644
--- a/src/soc/mediatek/mt8173/include/soc/dsi.h
+++ b/src/soc/mediatek/mt8173/include/soc/dsi.h
@@ -85,13 +85,13 @@
u8 reserved4[16];
u32 dsi_vm_cmd_con;
u8 reserved5[204];
- u32 dsi_cmdq0;
+ u32 dsi_cmdq[128];
};

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);
+check_member(dsi_regs, dsi_cmdq, 0x200);
static struct dsi_regs *const dsi0 = (void *)DSI0_BASE;
static struct dsi_regs *const dsi1 = (void *)DSI1_BASE;


To view, visit change 34773. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: Ie7c824873465ac82a95bcb0ed67b8b9866987008
Gerrit-Change-Number: 34773
Gerrit-PatchSet: 1
Gerrit-Owner: Hung-Te Lin <hungte@chromium.org>
Gerrit-Reviewer: Hung-Te Lin <hungte@chromium.org>
Gerrit-Reviewer: Julius Werner <jwerner@chromium.org>
Gerrit-MessageType: newchange