From 0499ce9f8319cac1078f4b2423e4e7b420611943 Mon Sep 17 00:00:00 2001 From: Lin Huang Date: Wed, 17 Jan 2018 14:24:14 +0800 Subject: rockchip/rk3399: Support LONG_WRITE type in MIPI DSI Some panels need to transfer initial code, and some of them will be over 3 bytes, so support LONG_WRITE type in driver. Refactor mipi dsi transfer function to support it. Change-Id: I212c14165e074c40a4a1a25140d9e8dfdfba465f Signed-off-by: Lin Huang Reviewed-on: https://review.coreboot.org/23299 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- src/mainboard/google/gru/mainboard.c | 242 ++++++++++++++--------------- src/soc/rockchip/rk3399/include/soc/mipi.h | 10 +- src/soc/rockchip/rk3399/mipi.c | 85 ++++++++-- 3 files changed, 201 insertions(+), 136 deletions(-) (limited to 'src') diff --git a/src/mainboard/google/gru/mainboard.c b/src/mainboard/google/gru/mainboard.c index 1212ad5bd0..101d7cd477 100644 --- a/src/mainboard/google/gru/mainboard.c +++ b/src/mainboard/google/gru/mainboard.c @@ -378,136 +378,137 @@ void mainboard_power_on_backlight(void) static struct panel_init_command kd097d04_init_commands[] = { /* voltage setting */ - { 0xB0, 0x00 }, - { 0xB2, 0x02 }, - { 0xB3, 0x11 }, - { 0xB4, 0x00 }, - { 0xB6, 0x80 }, + MIPI_INIT_CMD(0xB0, 0x00), + MIPI_INIT_CMD(0xB2, 0x02), + MIPI_INIT_CMD(0xB3, 0x11), + MIPI_INIT_CMD(0xB4, 0x00), + MIPI_INIT_CMD(0xB6, 0x80), /* VCOM disable */ - { 0xB8, 0x80 }, - { 0xBA, 0x43 }, + MIPI_INIT_CMD(0xB8, 0x80), + MIPI_INIT_CMD(0xBA, 0x43), /* VCOM setting */ - { 0xBB, 0x53 }, + MIPI_INIT_CMD(0xBB, 0x53), /* VSP setting */ - { 0xBC, 0x0A }, + MIPI_INIT_CMD(0xBC, 0x0A), /* VSN setting */ - { 0xBD, 0x4A }, + MIPI_INIT_CMD(0xBD, 0x4A), /* VGH setting */ - { 0xBE, 0x2F }, + MIPI_INIT_CMD(0xBE, 0x2F), /* VGL setting */ - { 0xBF, 0x1A }, - { 0xF0, 0x39 }, - { 0xF1, 0x21 }, + MIPI_INIT_CMD(0xBF, 0x1A), + MIPI_INIT_CMD(0xF0, 0x39), + MIPI_INIT_CMD(0xF1, 0x21), /* Gamma setting */ - { 0xB0, 0x02 }, - { 0xC0, 0x00 }, - { 0xC1, 0x01 }, - { 0xC2, 0x0B }, - { 0xC3, 0x15 }, - { 0xC4, 0x22 }, - { 0xC5, 0x11 }, - { 0xC6, 0x15 }, - { 0xC7, 0x19 }, - { 0xC8, 0x1A }, - { 0xC9, 0x16 }, - { 0xCA, 0x18 }, - { 0xCB, 0x13 }, - { 0xCC, 0x18 }, - { 0xCD, 0x13 }, - { 0xCE, 0x1C }, - { 0xCF, 0x19 }, - { 0xD0, 0x21 }, - { 0xD1, 0x2C }, - { 0xD2, 0x2F }, - { 0xD3, 0x30 }, - { 0xD4, 0x19 }, - { 0xD5, 0x1F }, - { 0xD6, 0x00 }, - { 0xD7, 0x01 }, - { 0xD8, 0x0B }, - { 0xD9, 0x15 }, - { 0xDA, 0x22 }, - { 0xDB, 0x11 }, - { 0xDC, 0x15 }, - { 0xDD, 0x19 }, - { 0xDE, 0x1A }, - { 0xDF, 0x16 }, - { 0xE0, 0x18 }, - { 0xE1, 0x13 }, - { 0xE2, 0x18 }, - { 0xE3, 0x13 }, - { 0xE4, 0x1C }, - { 0xE5, 0x19 }, - { 0xE6, 0x21 }, - { 0xE7, 0x2C }, - { 0xE8, 0x2F }, - { 0xE9, 0x30 }, - { 0xEA, 0x19 }, - { 0xEB, 0x1F }, + MIPI_INIT_CMD(0xB0, 0x02), + MIPI_INIT_CMD(0xC0, 0x00), + MIPI_INIT_CMD(0xC1, 0x01), + MIPI_INIT_CMD(0xC2, 0x0B), + MIPI_INIT_CMD(0xC3, 0x15), + MIPI_INIT_CMD(0xC4, 0x22), + MIPI_INIT_CMD(0xC5, 0x11), + MIPI_INIT_CMD(0xC6, 0x15), + MIPI_INIT_CMD(0xC7, 0x19), + MIPI_INIT_CMD(0xC8, 0x1A), + MIPI_INIT_CMD(0xC9, 0x16), + MIPI_INIT_CMD(0xCA, 0x18), + MIPI_INIT_CMD(0xCB, 0x13), + MIPI_INIT_CMD(0xCC, 0x18), + MIPI_INIT_CMD(0xCD, 0x13), + MIPI_INIT_CMD(0xCE, 0x1C), + MIPI_INIT_CMD(0xCF, 0x19), + MIPI_INIT_CMD(0xD0, 0x21), + MIPI_INIT_CMD(0xD1, 0x2C), + MIPI_INIT_CMD(0xD2, 0x2F), + MIPI_INIT_CMD(0xD3, 0x30), + MIPI_INIT_CMD(0xD4, 0x19), + MIPI_INIT_CMD(0xD5, 0x1F), + MIPI_INIT_CMD(0xD6, 0x00), + MIPI_INIT_CMD(0xD7, 0x01), + MIPI_INIT_CMD(0xD8, 0x0B), + MIPI_INIT_CMD(0xD9, 0x15), + MIPI_INIT_CMD(0xDA, 0x22), + MIPI_INIT_CMD(0xDB, 0x11), + MIPI_INIT_CMD(0xDC, 0x15), + MIPI_INIT_CMD(0xDD, 0x19), + MIPI_INIT_CMD(0xDE, 0x1A), + MIPI_INIT_CMD(0xDF, 0x16), + MIPI_INIT_CMD(0xE0, 0x18), + MIPI_INIT_CMD(0xE1, 0x13), + MIPI_INIT_CMD(0xE2, 0x18), + MIPI_INIT_CMD(0xE3, 0x13), + MIPI_INIT_CMD(0xE4, 0x1C), + MIPI_INIT_CMD(0xE5, 0x19), + MIPI_INIT_CMD(0xE6, 0x21), + MIPI_INIT_CMD(0xE7, 0x2C), + MIPI_INIT_CMD(0xE8, 0x2F), + MIPI_INIT_CMD(0xE9, 0x30), + MIPI_INIT_CMD(0xEA, 0x19), + MIPI_INIT_CMD(0xEB, 0x1F), /* GOA MUX setting */ - { 0xB0, 0x01 }, - { 0xC0, 0x10 }, - { 0xC1, 0x0F }, - { 0xC2, 0x0E }, - { 0xC3, 0x0D }, - { 0xC4, 0x0C }, - { 0xC5, 0x0B }, - { 0xC6, 0x0A }, - { 0xC7, 0x09 }, - { 0xC8, 0x08 }, - { 0xC9, 0x07 }, - { 0xCA, 0x06 }, - { 0xCB, 0x05 }, - { 0xCC, 0x00 }, - { 0xCD, 0x01 }, - { 0xCE, 0x02 }, - { 0xCF, 0x03 }, - { 0xD0, 0x04 }, - { 0xD6, 0x10 }, - { 0xD7, 0x0F }, - { 0xD8, 0x0E }, - { 0xD9, 0x0D }, - { 0xDA, 0x0C }, - { 0xDB, 0x0B }, - { 0xDC, 0x0A }, - { 0xDD, 0x09 }, - { 0xDE, 0x08 }, - { 0xDF, 0x07 }, - { 0xE0, 0x06 }, - { 0xE1, 0x05 }, - { 0xE2, 0x00 }, - { 0xE3, 0x01 }, - { 0xE4, 0x02 }, - { 0xE5, 0x03 }, - { 0xE6, 0x04 }, - { 0xE7, 0x00 }, - { 0xEC, 0xC0 }, + MIPI_INIT_CMD(0xB0, 0x01), + MIPI_INIT_CMD(0xC0, 0x10), + MIPI_INIT_CMD(0xC1, 0x0F), + MIPI_INIT_CMD(0xC2, 0x0E), + MIPI_INIT_CMD(0xC3, 0x0D), + MIPI_INIT_CMD(0xC4, 0x0C), + MIPI_INIT_CMD(0xC5, 0x0B), + MIPI_INIT_CMD(0xC6, 0x0A), + MIPI_INIT_CMD(0xC7, 0x09), + MIPI_INIT_CMD(0xC8, 0x08), + MIPI_INIT_CMD(0xC9, 0x07), + MIPI_INIT_CMD(0xCA, 0x06), + MIPI_INIT_CMD(0xCB, 0x05), + MIPI_INIT_CMD(0xCC, 0x00), + MIPI_INIT_CMD(0xCD, 0x01), + MIPI_INIT_CMD(0xCE, 0x02), + MIPI_INIT_CMD(0xCF, 0x03), + MIPI_INIT_CMD(0xD0, 0x04), + MIPI_INIT_CMD(0xD6, 0x10), + MIPI_INIT_CMD(0xD7, 0x0F), + MIPI_INIT_CMD(0xD8, 0x0E), + MIPI_INIT_CMD(0xD9, 0x0D), + MIPI_INIT_CMD(0xDA, 0x0C), + MIPI_INIT_CMD(0xDB, 0x0B), + MIPI_INIT_CMD(0xDC, 0x0A), + MIPI_INIT_CMD(0xDD, 0x09), + MIPI_INIT_CMD(0xDE, 0x08), + MIPI_INIT_CMD(0xDF, 0x07), + MIPI_INIT_CMD(0xE0, 0x06), + MIPI_INIT_CMD(0xE1, 0x05), + MIPI_INIT_CMD(0xE2, 0x00), + MIPI_INIT_CMD(0xE3, 0x01), + MIPI_INIT_CMD(0xE4, 0x02), + MIPI_INIT_CMD(0xE5, 0x03), + MIPI_INIT_CMD(0xE6, 0x04), + MIPI_INIT_CMD(0xE7, 0x00), + MIPI_INIT_CMD(0xEC, 0xC0), /* GOA timing setting */ - { 0xB0, 0x03 }, - { 0xC0, 0x01 }, - { 0xC2, 0x6F }, - { 0xC3, 0x6F }, - { 0xC5, 0x36 }, - { 0xC8, 0x08 }, - { 0xC9, 0x04 }, - { 0xCA, 0x41 }, - { 0xCC, 0x43 }, - { 0xCF, 0x60 }, - { 0xD2, 0x04 }, - { 0xD3, 0x04 }, - { 0xD4, 0x03 }, - { 0xD5, 0x02 }, - { 0xD6, 0x01 }, - { 0xD7, 0x00 }, - { 0xDB, 0x01 }, - { 0xDE, 0x36 }, - { 0xE6, 0x6F }, - { 0xE7, 0x6F }, + MIPI_INIT_CMD(0xB0, 0x03), + MIPI_INIT_CMD(0xC0, 0x01), + MIPI_INIT_CMD(0xC2, 0x6F), + MIPI_INIT_CMD(0xC3, 0x6F), + MIPI_INIT_CMD(0xC5, 0x36), + MIPI_INIT_CMD(0xC8, 0x08), + MIPI_INIT_CMD(0xC9, 0x04), + MIPI_INIT_CMD(0xCA, 0x41), + MIPI_INIT_CMD(0xCC, 0x43), + MIPI_INIT_CMD(0xCF, 0x60), + MIPI_INIT_CMD(0xD2, 0x04), + MIPI_INIT_CMD(0xD3, 0x04), + MIPI_INIT_CMD(0xD4, 0x03), + MIPI_INIT_CMD(0xD5, 0x02), + MIPI_INIT_CMD(0xD6, 0x01), + MIPI_INIT_CMD(0xD7, 0x00), + MIPI_INIT_CMD(0xDB, 0x01), + MIPI_INIT_CMD(0xDE, 0x36), + MIPI_INIT_CMD(0xE6, 0x6F), + MIPI_INIT_CMD(0xE7, 0x6F), /* GOE setting */ - { 0xB0, 0x06 }, - { 0xB8, 0xA5 }, - { 0xC0, 0xA5 }, - { 0xD5, 0x3F }, + MIPI_INIT_CMD(0xB0, 0x06), + MIPI_INIT_CMD(0xB8, 0xA5), + MIPI_INIT_CMD(0xC0, 0xA5), + MIPI_INIT_CMD(0xD5, 0x3F), + {}, }; const struct mipi_panel_data kd097d04_panel = { @@ -517,7 +518,6 @@ const struct mipi_panel_data kd097d04_panel = { .display_on_udelay = 120000, .video_mode_udelay = 5000, .init_cmd = kd097d04_init_commands, - .num_init_commands = ARRAY_SIZE(kd097d04_init_commands) }; static const struct edid_mode kd097d04_edid_mode = { diff --git a/src/soc/rockchip/rk3399/include/soc/mipi.h b/src/soc/rockchip/rk3399/include/soc/mipi.h index 933ea89bd4..457c51dd1e 100644 --- a/src/soc/rockchip/rk3399/include/soc/mipi.h +++ b/src/soc/rockchip/rk3399/include/soc/mipi.h @@ -264,9 +264,14 @@ check_member(rk_mipi_regs, dsi_int_msk1, 0xc8); #define GEN_RD_CMD_BUSY BIT(6) #define MIPI_DSI_DCS_SHORT_WRITE 0x05 +#define MIPI_DSI_DCS_SHORT_WRITE_PARAM 0x15 #define MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM 0x23 #define MIPI_DSI_DCS_LONG_WRITE 0x39 +#define MIPI_INIT_CMD(...) { \ + .len = sizeof((char[]){__VA_ARGS__}), \ + .data = (char[]){__VA_ARGS__} } + enum mipi_dsi_pixel_format { MIPI_DSI_FMT_RGB888, MIPI_DSI_FMT_RGB666, @@ -324,8 +329,8 @@ struct rk_mipi_dsi { }; struct panel_init_command { - u8 cmd; - u8 data; + int len; + char *data; }; struct mipi_panel_data { @@ -334,7 +339,6 @@ struct mipi_panel_data { u8 lanes; u32 display_on_udelay; u32 video_mode_udelay; - u32 num_init_commands; struct panel_init_command *init_cmd; }; diff --git a/src/soc/rockchip/rk3399/mipi.c b/src/soc/rockchip/rk3399/mipi.c index 825eb72366..813746e01e 100644 --- a/src/soc/rockchip/rk3399/mipi.c +++ b/src/soc/rockchip/rk3399/mipi.c @@ -549,7 +549,7 @@ static void rk_mipi_message_config(struct rk_mipi_dsi *dsi) write32(&dsi->mipi_regs->dsi_cmd_mode_cfg, CMD_MODE_ALL_LP); } -static int rk_mipi_dsi_check_cmd_fifo(struct rk_mipi_dsi *dsi) +static int rk_mipi_dsi_check_fifo(struct rk_mipi_dsi *dsi, u32 flag) { struct stopwatch sw; int val; @@ -557,7 +557,7 @@ static int rk_mipi_dsi_check_cmd_fifo(struct rk_mipi_dsi *dsi) stopwatch_init_msecs_expire(&sw, 20); do { val = read32(&dsi->mipi_regs->dsi_cmd_pkt_status); - if (!(val & GEN_CMD_FULL)) + if (!(val & flag)) return 0 ; } while (!stopwatch_expired(&sw)); @@ -570,7 +570,7 @@ static int rk_mipi_dsi_gen_pkt_hdr_write(struct rk_mipi_dsi *dsi, u32 hdr_val) struct stopwatch sw; u32 mask; - if (rk_mipi_dsi_check_cmd_fifo(dsi)) { + if (rk_mipi_dsi_check_fifo(dsi, GEN_CMD_FULL)) { printk(BIOS_ERR, "failed to get available command FIFO\n"); return -1; } @@ -600,15 +600,65 @@ static int rk_mipi_dsi_dcs_cmd(struct rk_mipi_dsi *dsi, u8 cmd) return rk_mipi_dsi_gen_pkt_hdr_write(dsi, val); } -static int rk_mipi_dsi_dci_cmd_arg(struct rk_mipi_dsi *dsi, u8 cmd, u8 arg) +static int rk_mipi_dsi_dci_long_write(struct rk_mipi_dsi *dsi, + char *data, u32 len) { + u32 remainder; + int ret = 0; + + while (len) { + if (len < 4) { + remainder = 0; + memcpy(&remainder, data, len); + write32(&dsi->mipi_regs->dsi_gen_pld_data, remainder); + len = 0; + } else { + remainder = *(u32 *)data; + write32(&dsi->mipi_regs->dsi_gen_pld_data, remainder); + data += 4; + len -= 4; + } + + ret = rk_mipi_dsi_check_fifo(dsi, GEN_PLD_W_FULL); + if (ret) { + printk(BIOS_ERR, "Failed to write fifo\n"); + return ret; + } + } + + return ret; +} + +static int rk_mipi_dsi_write(struct rk_mipi_dsi *dsi, char *data, int len) +{ + u16 buf = 0; u32 val; - u16 data; + int ret = 0; rk_mipi_message_config(dsi); - data = cmd | (arg << 8); - val = GEN_HDATA(data) | GEN_HTYPE(MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM); + switch (len) { + case 0: + die("not data!"); + case 1: + val = GEN_HDATA(*data) | + GEN_HTYPE(MIPI_DSI_DCS_SHORT_WRITE); + break; + case 2: + buf = *data++; + buf |= *data << 8; + val = GEN_HDATA(buf) | + GEN_HTYPE(MIPI_DSI_DCS_SHORT_WRITE_PARAM); + break; + default: + ret = rk_mipi_dsi_dci_long_write(dsi, data, len); + if (ret) { + printk(BIOS_ERR, "error happened during long write\n"); + return ret; + } + val = GEN_HDATA(len) | GEN_HTYPE(MIPI_DSI_DCS_LONG_WRITE); + break; + } return rk_mipi_dsi_gen_pkt_hdr_write(dsi, val); } @@ -642,6 +692,7 @@ void rk_mipi_prepare(const struct edid *edid, const struct mipi_panel_data *panel_data) { int i, num; + struct panel_init_command *cmds; for (i = 0; i < panel_data->mipi_num; i++) { rk_mipi[i].lanes = panel_data->lanes / panel_data->mipi_num; @@ -649,11 +700,21 @@ void rk_mipi_prepare(const struct edid *edid, rk_mipi_enable(&rk_mipi[i], edid, panel_data); } - for (num = 0; num < panel_data->num_init_commands; num++) { - for (i = 0; i < panel_data->mipi_num; i++) - rk_mipi_dsi_dci_cmd_arg(&rk_mipi[i], - panel_data->init_cmd[num].cmd, - panel_data->init_cmd[num].data); + if (panel_data->init_cmd) { + cmds = panel_data->init_cmd; + for (num = 0; cmds[num].len != 0; num++) { + struct panel_init_command *cmd = &cmds[num]; + for (i = 0; i < panel_data->mipi_num; i++) { + if (rk_mipi_dsi_write(&rk_mipi[i], cmd->data, + cmd->len)) + return; + + /* make sure panel picks up the command */ + if (rk_mipi_dsi_dcs_cmd(&rk_mipi[i], + MIPI_DCS_NOP)) + return; + } + } } for (i = 0; i < panel_data->mipi_num; i++) { -- cgit v1.2.3