disp: msm: dsi: add debug ability to read TE read pointer line count

The change adds register mapping of MDP_INTF_[1/2]_TEAR_INT_COUNT_VAL
register to DSI controller. This allows for the controller to read the
line count and frame count of the read pointer during trigger and
successful transfer of DMA command.

To enable the debug feature:
echo 1 > /d/<panel_name>/dsi-ctrl-0/enable_cmd_dma_stats.

To disable the debug feature
echo 0 > /d/<panel_name>/dsi-ctrl-0/enable_cmd_dma_stats.

To read line count value:
cat /d/<panel_name>/dsi-ctrl-0/cmd_dma_stats.

Change-Id: I5cdeb54ca941af05b226a9d7ab332b899ecc5797
Signed-off-by: Satya Rama Aditya Pinapala <psraditya30@codeaurora.org>
This commit is contained in:
Satya Rama Aditya Pinapala
2020-07-15 02:10:24 -07:00
parent 50af1eb43b
commit 3deb5c353e
6 changed files with 264 additions and 2 deletions

View File

@@ -194,6 +194,58 @@ static ssize_t debugfs_reg_dump_read(struct file *file,
return len;
}
static ssize_t debugfs_line_count_read(struct file *file,
char __user *user_buf,
size_t user_len,
loff_t *ppos)
{
struct dsi_ctrl *dsi_ctrl = file->private_data;
char *buf;
int rc = 0;
u32 len = 0;
size_t max_len = min_t(size_t, user_len, SZ_4K);
if (!dsi_ctrl)
return -ENODEV;
if (*ppos)
return 0;
buf = kzalloc(max_len, GFP_KERNEL);
if (ZERO_OR_NULL_PTR(buf))
return -ENOMEM;
mutex_lock(&dsi_ctrl->ctrl_lock);
len += scnprintf(buf, max_len, "Command triggered at line: %04x\n",
dsi_ctrl->cmd_trigger_line);
len += scnprintf((buf + len), max_len - len,
"Command triggered at frame: %04x\n",
dsi_ctrl->cmd_trigger_frame);
len += scnprintf((buf + len), max_len - len,
"Command successful at line: %04x\n",
dsi_ctrl->cmd_success_line);
len += scnprintf((buf + len), max_len - len,
"Command successful at frame: %04x\n",
dsi_ctrl->cmd_success_frame);
mutex_unlock(&dsi_ctrl->ctrl_lock);
if (len > max_len)
len = max_len;
if (copy_to_user(user_buf, buf, len)) {
rc = -EFAULT;
goto error;
}
*ppos += len;
error:
kfree(buf);
return len;
}
static const struct file_operations state_info_fops = {
.open = simple_open,
.read = debugfs_state_info_read,
@@ -204,11 +256,16 @@ static const struct file_operations reg_dump_fops = {
.read = debugfs_reg_dump_read,
};
static const struct file_operations cmd_dma_stats_fops = {
.open = simple_open,
.read = debugfs_line_count_read,
};
static int dsi_ctrl_debugfs_init(struct dsi_ctrl *dsi_ctrl,
struct dentry *parent)
{
int rc = 0;
struct dentry *dir, *state_file, *reg_dump;
struct dentry *dir, *state_file, *reg_dump, *cmd_dma_logs;
char dbg_name[DSI_DEBUG_NAME_LEN];
if (!dsi_ctrl || !parent) {
@@ -246,6 +303,30 @@ static int dsi_ctrl_debugfs_init(struct dsi_ctrl *dsi_ctrl,
goto error_remove_dir;
}
cmd_dma_logs = debugfs_create_bool("enable_cmd_dma_stats",
0600,
dir,
&dsi_ctrl->enable_cmd_dma_stats);
if (IS_ERR_OR_NULL(cmd_dma_logs)) {
rc = PTR_ERR(cmd_dma_logs);
DSI_CTRL_ERR(dsi_ctrl,
"enable cmd dma stats failed, rc=%d\n",
rc);
goto error_remove_dir;
}
cmd_dma_logs = debugfs_create_file("cmd_dma_stats",
0444,
dir,
dsi_ctrl,
&cmd_dma_stats_fops);
if (IS_ERR_OR_NULL(cmd_dma_logs)) {
rc = PTR_ERR(cmd_dma_logs);
DSI_CTRL_ERR(dsi_ctrl, "Line count file failed, rc=%d\n",
rc);
goto error_remove_dir;
}
dsi_ctrl->debugfs_root = dir;
snprintf(dbg_name, DSI_DEBUG_NAME_LEN, "dsi%d_ctrl",
@@ -1250,6 +1331,8 @@ static void dsi_kickoff_msg_tx(struct dsi_ctrl *dsi_ctrl,
if (flags & DSI_CTRL_CMD_CUSTOM_DMA_SCHED)
dsi_configure_command_scheduling(dsi_ctrl, cmd_mem);
dsi_ctrl->cmd_mode = (dsi_ctrl->host_config.panel_mode ==
DSI_OP_CMD_MODE);
hw_flags |= (flags & DSI_CTRL_CMD_DEFER_TRIGGER) ?
DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER : 0;
@@ -1304,6 +1387,17 @@ static void dsi_kickoff_msg_tx(struct dsi_ctrl *dsi_ctrl,
cmd,
hw_flags);
}
if (dsi_ctrl->enable_cmd_dma_stats) {
u32 reg = dsi_hw_ops.log_line_count(&dsi_ctrl->hw,
dsi_ctrl->cmd_mode);
dsi_ctrl->cmd_trigger_line = (reg & 0xFFFF);
dsi_ctrl->cmd_trigger_frame = ((reg >> 16) & 0xFFFF);
SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_CASE1,
dsi_ctrl->cmd_trigger_line,
dsi_ctrl->cmd_trigger_frame);
}
if (flags & DSI_CTRL_CMD_ASYNC_WAIT) {
dsi_ctrl->dma_wait_queued = true;
queue_work(dsi_ctrl->dma_cmd_workq,
@@ -1966,6 +2060,9 @@ static int dsi_ctrl_dev_probe(struct platform_device *pdev)
goto fail_clks;
}
if (dsi_ctrl->hw.ops.map_mdp_regs)
dsi_ctrl->hw.ops.map_mdp_regs(pdev, &dsi_ctrl->hw);
item->ctrl = dsi_ctrl;
sde_dbg_dsi_ctrl_register(dsi_ctrl->hw.base, dsi_ctrl->name);
@@ -2629,6 +2726,15 @@ static irqreturn_t dsi_ctrl_isr(int irq, void *ptr)
dsi_ctrl_handle_error_status(dsi_ctrl, errors);
if (status & DSI_CMD_MODE_DMA_DONE) {
if (dsi_ctrl->enable_cmd_dma_stats) {
u32 reg = dsi_ctrl->hw.ops.log_line_count(&dsi_ctrl->hw,
dsi_ctrl->cmd_mode);
dsi_ctrl->cmd_success_line = (reg & 0xFFFF);
dsi_ctrl->cmd_success_frame = ((reg >> 16) & 0xFFFF);
SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_CASE1,
dsi_ctrl->cmd_success_line,
dsi_ctrl->cmd_success_frame);
}
atomic_set(&dsi_ctrl->dma_irq_trig, 1);
dsi_ctrl_disable_status_interrupt(dsi_ctrl,
DSI_SINT_CMD_MODE_DMA_DONE);
@@ -3236,8 +3342,18 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags)
mutex_lock(&dsi_ctrl->ctrl_lock);
if (!(flags & DSI_CTRL_CMD_BROADCAST_MASTER))
if (!(flags & DSI_CTRL_CMD_BROADCAST_MASTER)) {
dsi_hw_ops.trigger_command_dma(&dsi_ctrl->hw);
if (dsi_ctrl->enable_cmd_dma_stats) {
u32 reg = dsi_hw_ops.log_line_count(&dsi_ctrl->hw,
dsi_ctrl->cmd_mode);
dsi_ctrl->cmd_trigger_line = (reg & 0xFFFF);
dsi_ctrl->cmd_trigger_frame = ((reg >> 16) & 0xFFFF);
SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_CASE1,
dsi_ctrl->cmd_trigger_line,
dsi_ctrl->cmd_trigger_frame);
}
}
if ((flags & DSI_CTRL_CMD_BROADCAST) &&
(flags & DSI_CTRL_CMD_BROADCAST_MASTER)) {
@@ -3252,6 +3368,17 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags)
/* trigger command */
dsi_hw_ops.trigger_command_dma(&dsi_ctrl->hw);
if (dsi_ctrl->enable_cmd_dma_stats) {
u32 reg = dsi_hw_ops.log_line_count(&dsi_ctrl->hw,
dsi_ctrl->cmd_mode);
dsi_ctrl->cmd_trigger_line = (reg & 0xFFFF);
dsi_ctrl->cmd_trigger_frame = ((reg >> 16) & 0xFFFF);
SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_CASE1,
dsi_ctrl->cmd_trigger_line,
dsi_ctrl->cmd_trigger_frame);
}
if (flags & DSI_CTRL_CMD_ASYNC_WAIT) {
dsi_ctrl->dma_wait_queued = true;
queue_work(dsi_ctrl->dma_cmd_workq,