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_ */