diff --git a/msm/dsi/dsi_ctrl.c b/msm/dsi/dsi_ctrl.c index 8aa33724ce..a92f05eaac 100644 --- a/msm/dsi/dsi_ctrl.c +++ b/msm/dsi/dsi_ctrl.c @@ -2855,6 +2855,8 @@ static irqreturn_t dsi_ctrl_isr(int irq, void *ptr) dsi_ctrl->cmd_success_line, dsi_ctrl->cmd_success_frame); } + + dsi_ctrl->cmd_success_ts = ktime_get(); atomic_set(&dsi_ctrl->dma_irq_trig, 1); dsi_ctrl_disable_status_interrupt(dsi_ctrl, DSI_SINT_CMD_MODE_DMA_DONE); @@ -3501,6 +3503,7 @@ int dsi_ctrl_cmd_transfer(struct dsi_ctrl *dsi_ctrl, struct dsi_cmd_desc *cmd) rc); } + cmd->ts = dsi_ctrl->cmd_success_ts; dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_CMD_TX, 0x0); mutex_unlock(&dsi_ctrl->ctrl_lock); diff --git a/msm/dsi/dsi_ctrl.h b/msm/dsi/dsi_ctrl.h index 858b712fbe..2100b8ecf8 100644 --- a/msm/dsi/dsi_ctrl.h +++ b/msm/dsi/dsi_ctrl.h @@ -253,6 +253,7 @@ struct dsi_ctrl_interrupts { * which command transfer is successful. * @cmd_engine_refcount: Reference count enforcing single instance of cmd engine * @pending_cmd_flags: Flags associated with command that is currently being txed or pending. + * @cmd_success_ts: Time stamp of when command transfer is successful in nano-seconds. */ struct dsi_ctrl { struct platform_device *pdev; @@ -321,6 +322,7 @@ struct dsi_ctrl { u32 cmd_success_frame; u32 cmd_engine_refcount; u32 pending_cmd_flags; + ktime_t cmd_success_ts; }; /** diff --git a/msm/dsi/dsi_defs.h b/msm/dsi/dsi_defs.h index d7329bfb62..2c7a18f350 100644 --- a/msm/dsi/dsi_defs.h +++ b/msm/dsi/dsi_defs.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -366,6 +366,7 @@ enum dsi_video_traffic_mode { * @post_wait_ms: post wait duration * @ctrl: index of DSI controller * @ctrl_flags: controller flags + * @ts: dsi command time stamp in nano-seconds. */ struct dsi_cmd_desc { struct mipi_dsi_msg msg; @@ -373,6 +374,7 @@ struct dsi_cmd_desc { u32 post_wait_ms; u32 ctrl; u32 ctrl_flags; + ktime_t ts; }; /** diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 8d46762b0d..eb3b337dc1 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -9,6 +9,7 @@ #include #include #include +#include #include "msm_drv.h" #include "sde_connector.h" @@ -1229,7 +1230,7 @@ static void _dsi_display_continuous_clk_ctrl(struct dsi_display *display, } int dsi_display_cmd_receive(void *display, const char *cmd_buf, - u32 cmd_buf_len, u8 *recv_buf, u32 recv_buf_len) + u32 cmd_buf_len, u8 *recv_buf, u32 recv_buf_len, ktime_t *ts) { struct dsi_display *dsi_display = display; struct dsi_cmd_desc cmd = {}; @@ -1282,6 +1283,9 @@ int dsi_display_cmd_receive(void *display, const char *cmd_buf, if (rc <= 0) DSI_ERR("[DSI] Display command receive failed, rc=%d\n", rc); + if (ts) + *ts = cmd.ts; + end: mutex_unlock(&dsi_display->display_lock); return rc; @@ -7414,6 +7418,34 @@ int dsi_display_update_transfer_time(void *display, u32 transfer_time) return 0; } +int dsi_display_get_panel_scan_line(void *display, u16 *scan_line, ktime_t *scan_line_ts) +{ + struct dsi_display *dsi_display = (struct dsi_display *)display; + u8 scan_line_tx_buffer[] = {0x6, 0x1, 0x0, 0xa, 0x0, 0x0, 0x1, 0x45}; + u8 rx_buffer[2]; + int rx_len, rc = 0; + ktime_t ts = 0; + + if (!dsi_display || !scan_line || !scan_line_ts) + return -EINVAL; + + SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY); + rx_len = dsi_display_cmd_receive(dsi_display, scan_line_tx_buffer, + ARRAY_SIZE(scan_line_tx_buffer), rx_buffer, ARRAY_SIZE(rx_buffer), &ts); + if (rx_len <= 0) { + rc = -EINVAL; + goto end; + } + + *scan_line = (rx_buffer[0] << 8) | rx_buffer[1]; + *scan_line_ts = ts; + +end: + SDE_EVT32(SDE_EVTLOG_FUNC_EXIT, rx_len, rx_buffer[0], rx_buffer[1], + ktime_us_delta(ktime_get(), ts)); + return rc; +} + static bool dsi_display_match_timings(const struct dsi_display_mode *mode1, struct dsi_display_mode *mode2, unsigned int match_flags) { diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index ea7b5055a7..d3635a357a 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -710,9 +711,10 @@ int dsi_display_cmd_transfer(struct drm_connector *connector, * @cmd_buf_len: Command buffer length in bytes * @recv_buf: Receive buffer * @recv_buf_len: Receive buffer length in bytes + * @ts: Command time stamp in nano-seconds. */ int dsi_display_cmd_receive(void *display, const char *cmd_buf, - u32 cmd_buf_len, u8 *recv_buf, u32 recv_buf_len); + u32 cmd_buf_len, u8 *recv_buf, u32 recv_buf_len, ktime_t *ts); /** * dsi_display_soft_reset() - perform a soft reset on DSI controller @@ -844,4 +846,14 @@ bool dsi_display_mode_match(const struct dsi_display_mode *mode1, */ int dsi_display_update_transfer_time(void *display, u32 transfer_time); +/** + * dsi_display_get_panel_scan_line() - get panel scan line + * @display: handle to display + * @scan_line: scan line buffer value + * @scan_line_ts: scan line time stamp value in nano-seconds + * + * Return: error code + */ +int dsi_display_get_panel_scan_line(void *display, u16 *scan_line, ktime_t *scan_line_ts); + #endif /* _DSI_DISPLAY_H_ */ diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index c336e8f595..1fc11c35da 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -2468,7 +2468,7 @@ static ssize_t _sde_debugfs_conn_cmd_rx_write(struct file *file, mutex_lock(&c_conn->lock); c_conn->rx_len = c_conn->ops.cmd_receive(c_conn->display, buffer + 1, - buf_size - 1, c_conn->cmd_rx_buf, buffer[0]); + buf_size - 1, c_conn->cmd_rx_buf, buffer[0], NULL); mutex_unlock(&c_conn->lock); if (c_conn->rx_len <= 0) diff --git a/msm/sde/sde_connector.h b/msm/sde/sde_connector.h index 86ff2ace80..f700309ae8 100644 --- a/msm/sde/sde_connector.h +++ b/msm/sde/sde_connector.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -287,11 +287,12 @@ struct sde_connector_ops { * @cmd_buf_len: Command buffer length in bytes * @recv_buf: rx buffer * @recv_buf_len: rx buffer length + * @ts: time stamp in nano-seconds of when the command was received * Returns: number of bytes read, if successful, negative for failure */ int (*cmd_receive)(void *display, const char *cmd_buf, - u32 cmd_buf_len, u8 *recv_buf, u32 recv_buf_len); + u32 cmd_buf_len, u8 *recv_buf, u32 recv_buf_len, ktime_t *ts); /** * config_hdr - configure HDR @@ -438,6 +439,14 @@ struct sde_connector_ops { */ int (*update_transfer_time)(void *display, u32 transfer_time); + /* + * get_panel_scan_line - get panel scan line + * @display: Pointer to private display structure + * @scan_line: Pointer to scan_line buffer value + * @scan_line_ts: scan line time stamp value in nano-seconds + */ + int (*get_panel_scan_line)(void *display, u16 *scan_line, ktime_t *scan_line_ts); + }; /** diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 88298bc281..d90355e084 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark @@ -1834,6 +1834,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .set_submode_info = dsi_conn_set_submode_blob_info, .get_num_lm_from_mode = dsi_conn_get_lm_from_mode, .update_transfer_time = dsi_display_update_transfer_time, + .get_panel_scan_line = dsi_display_get_panel_scan_line, }; static const struct sde_connector_ops wb_ops = { .post_init = sde_wb_connector_post_init,