From bbe18a1689e40f40336e1e943961af0049f1ba00 Mon Sep 17 00:00:00 2001 From: Satya Rama Aditya Pinapala Date: Wed, 14 Oct 2020 06:52:24 -0700 Subject: [PATCH] disp: msm: dsi: batching multiple DSI commands using debugfs node The change batches DSI commands sent using the debugfs node, in a separate buffer from the TX command buffer to ensure that they are not triggered before the last command bit is set. Once the last command bit is set the buffer is then copied to the DSI TX buffer and triggered. Change-Id: I9ba624e4e19341696a974994817603315c6c8a45 Signed-off-by: Satya Rama Aditya Pinapala --- msm/dsi/dsi_ctrl.c | 26 ++++++++++++++-- msm/dsi/dsi_display.c | 71 +++++++++++++++++++++++++++++++++++-------- msm/dsi/dsi_display.h | 5 +++ msm/dsi/dsi_panel.c | 10 +++--- msm/dsi/dsi_panel.h | 11 +++++++ 5 files changed, 103 insertions(+), 20 deletions(-) diff --git a/msm/dsi/dsi_ctrl.c b/msm/dsi/dsi_ctrl.c index 8caa7fc78b..3e5dfeb6f9 100644 --- a/msm/dsi/dsi_ctrl.c +++ b/msm/dsi/dsi_ctrl.c @@ -1352,7 +1352,8 @@ static void dsi_kickoff_msg_tx(struct dsi_ctrl *dsi_ctrl, hw_flags |= (flags & DSI_CTRL_CMD_DEFER_TRIGGER) ? DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER : 0; - if ((msg->flags & MIPI_DSI_MSG_LASTCOMMAND)) + if ((msg->flags & MIPI_DSI_MSG_LASTCOMMAND) || + (flags & DSI_CTRL_CMD_LAST_COMMAND)) hw_flags |= DSI_CTRL_CMD_LAST_COMMAND; if (flags & DSI_CTRL_CMD_DEFER_TRIGGER) { @@ -1488,6 +1489,8 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, dsi_ctrl_validate_msg_flags(dsi_ctrl, msg, flags); + SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_ENTRY, flags); + if (dsi_ctrl->dma_wait_queued) dsi_ctrl_flush_cmd_dma_queue(dsi_ctrl); @@ -1527,7 +1530,23 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, goto error; } - if ((msg->flags & MIPI_DSI_MSG_LASTCOMMAND)) + /* + * In case of broadcast CMD length cannot be greater than 512 bytes + * as specified by HW limitations. Need to overwrite the flags to + * set the LAST_COMMAND flag to ensure no command transfer failures. + */ + if ((*flags & DSI_CTRL_CMD_FETCH_MEMORY) && + (*flags & DSI_CTRL_CMD_BROADCAST)) { + if ((dsi_ctrl->cmd_len + length) > 240) { + dsi_ctrl_mask_overflow(dsi_ctrl, true); + *flags |= DSI_CTRL_CMD_LAST_COMMAND; + SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_CASE1, + flags); + } + } + + if ((msg->flags & MIPI_DSI_MSG_LASTCOMMAND) || + (*flags & DSI_CTRL_CMD_LAST_COMMAND)) buffer[3] |= BIT(7);//set the last cmd bit in header. if (*flags & DSI_CTRL_CMD_FETCH_MEMORY) { @@ -1548,7 +1567,8 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl, dsi_ctrl->cmd_len += length; - if (!(msg->flags & MIPI_DSI_MSG_LASTCOMMAND)) { + if (!(msg->flags & MIPI_DSI_MSG_LASTCOMMAND) && + !(*flags & DSI_CTRL_CMD_LAST_COMMAND)) { goto error; } else { cmd_mem.length = dsi_ctrl->cmd_len; diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 828def97b1..82715197a1 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -36,6 +36,7 @@ #define SEC_PANEL_NAME_MAX_LEN 256 +u8 dbgfs_tx_cmd_buf[SZ_4K]; static char dsi_display_primary[MAX_CMDLINE_PARAM_LEN]; static char dsi_display_secondary[MAX_CMDLINE_PARAM_LEN]; static struct dsi_display_boot_param boot_displays[MAX_DSI_ACTIVE_DISPLAY] = { @@ -1014,10 +1015,9 @@ int dsi_display_cmd_transfer(struct drm_connector *connector, u32 cmd_buf_len) { struct dsi_display *dsi_display = display; - struct dsi_cmd_desc cmd; - u8 cmd_payload[MAX_CMD_PAYLOAD_SIZE]; - int rc = 0; - bool state = false; + int rc = 0, cnt = 0, i = 0; + bool state = false, transfer = false; + struct dsi_panel_cmd_set *set; if (!dsi_display || !cmd_buf) { DSI_ERR("[DSI] invalid params\n"); @@ -1026,12 +1026,8 @@ int dsi_display_cmd_transfer(struct drm_connector *connector, DSI_DEBUG("[DSI] Display command transfer\n"); - rc = dsi_display_cmd_prepare(cmd_buf, cmd_buf_len, - &cmd, cmd_payload, MAX_CMD_PAYLOAD_SIZE); - if (rc) { - DSI_ERR("[DSI] command prepare failed. rc %d\n", rc); - return rc; - } + if ((cmd_buf[1]) || (cmd_buf[3] & MIPI_DSI_MSG_LASTCOMMAND)) + transfer = true; mutex_lock(&dsi_display->display_lock); rc = dsi_display_ctrl_get_host_init_state(dsi_display, &state); @@ -1053,8 +1049,59 @@ int dsi_display_cmd_transfer(struct drm_connector *connector, goto end; } - rc = dsi_display->host.ops->transfer(&dsi_display->host, - &cmd.msg); + /* + * Reset the dbgfs buffer if the commands sent exceed the available + * buffer size. For video mode, limiting the buffer size to 2K to + * ensure no performance issues. + */ + if (dsi_display->panel->panel_mode == DSI_OP_CMD_MODE) { + if ((dsi_display->tx_cmd_buf_ndx + cmd_buf_len) > SZ_4K) { + memset(dbgfs_tx_cmd_buf, 0, SZ_4K); + dsi_display->tx_cmd_buf_ndx = 0; + } + } else { + if ((dsi_display->tx_cmd_buf_ndx + cmd_buf_len) > SZ_2K) { + memset(dbgfs_tx_cmd_buf, 0, SZ_4K); + dsi_display->tx_cmd_buf_ndx = 0; + } + } + + memcpy(&dbgfs_tx_cmd_buf[dsi_display->tx_cmd_buf_ndx], cmd_buf, + cmd_buf_len); + dsi_display->tx_cmd_buf_ndx += cmd_buf_len; + if (transfer) { + struct dsi_cmd_desc *cmds; + + set = &dsi_display->cmd_set; + set->count = 0; + dsi_panel_get_cmd_pkt_count(dbgfs_tx_cmd_buf, + dsi_display->tx_cmd_buf_ndx, &cnt); + dsi_panel_alloc_cmd_packets(set, cnt); + dsi_panel_create_cmd_packets(dbgfs_tx_cmd_buf, + dsi_display->tx_cmd_buf_ndx, cnt, set->cmds); + cmds = set->cmds; + dsi_display->tx_cmd_buf_ndx = 0; + + for (i = 0; i < cnt; i++) { + if (cmds->last_command) + cmds->msg.flags |= MIPI_DSI_MSG_LASTCOMMAND; + rc = dsi_display->host.ops->transfer(&dsi_display->host, + &cmds->msg); + if (rc < 0) { + DSI_ERR("failed to send command, rc=%d\n", rc); + goto end; + } + if (cmds->post_wait_ms) + usleep_range(cmds->post_wait_ms*1000, + ((cmds->post_wait_ms*1000)+10)); + cmds++; + } + + memset(dbgfs_tx_cmd_buf, 0, SZ_4K); + dsi_panel_destroy_cmd_packets(set); + dsi_panel_dealloc_cmd_packets(set); + } + end: mutex_unlock(&dsi_display->display_lock); return rc; diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index b732c231f7..d29a76e760 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -192,6 +192,8 @@ struct dsi_display_ext_bridge { * @is_active: status of the display * @trusted_vm_env: Set to true, it the executing VM is Trusted VM. * Set to false, otherwise. + * @tx_cmd_buf_ndx: Index to the DSI debugfs TX CMD buffer. + * @cmd_set: Debugfs TX cmd set. */ struct dsi_display { struct platform_device *pdev; @@ -287,6 +289,9 @@ struct dsi_display { bool is_active; bool trusted_vm_env; + + int tx_cmd_buf_ndx; + struct dsi_panel_cmd_set cmd_set; }; int dsi_display_dev_probe(struct platform_device *pdev); diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index ea364f78ac..a7daa639e4 100644 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -1730,7 +1730,7 @@ const char *cmd_set_state_map[DSI_CMD_SET_MAX] = { "qcom,mdss-dsi-qsync-off-commands-state", }; -static int dsi_panel_get_cmd_pkt_count(const char *data, u32 length, u32 *cnt) +int dsi_panel_get_cmd_pkt_count(const char *data, u32 length, u32 *cnt) { const u32 cmd_set_min_size = 7; u32 count = 0; @@ -1754,7 +1754,7 @@ static int dsi_panel_get_cmd_pkt_count(const char *data, u32 length, u32 *cnt) return 0; } -static int dsi_panel_create_cmd_packets(const char *data, +int dsi_panel_create_cmd_packets(const char *data, u32 length, u32 count, struct dsi_cmd_desc *cmd) @@ -1799,7 +1799,7 @@ error_free_payloads: return rc; } -static void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set) +void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set) { u32 i = 0; struct dsi_cmd_desc *cmd; @@ -1810,12 +1810,12 @@ static void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set) } } -static void dsi_panel_dealloc_cmd_packets(struct dsi_panel_cmd_set *set) +void dsi_panel_dealloc_cmd_packets(struct dsi_panel_cmd_set *set) { kfree(set->cmds); } -static int dsi_panel_alloc_cmd_packets(struct dsi_panel_cmd_set *cmd, +int dsi_panel_alloc_cmd_packets(struct dsi_panel_cmd_set *cmd, u32 packet_count) { u32 size; diff --git a/msm/dsi/dsi_panel.h b/msm/dsi/dsi_panel.h index 439144ae93..02f04bb32d 100644 --- a/msm/dsi/dsi_panel.h +++ b/msm/dsi/dsi_panel.h @@ -378,4 +378,15 @@ int dsi_panel_get_io_resources(struct dsi_panel *panel, void dsi_panel_calc_dsi_transfer_time(struct dsi_host_common_cfg *config, struct dsi_display_mode *mode, u32 frame_threshold_us); +int dsi_panel_get_cmd_pkt_count(const char *data, u32 length, u32 *cnt); + +int dsi_panel_alloc_cmd_packets(struct dsi_panel_cmd_set *cmd, + u32 packet_count); + +int dsi_panel_create_cmd_packets(const char *data, u32 length, u32 count, + struct dsi_cmd_desc *cmd); + +void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set); + +void dsi_panel_dealloc_cmd_packets(struct dsi_panel_cmd_set *set); #endif /* _DSI_PANEL_H_ */