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

Bu işleme şunda yer alıyor:
qctecmdr
2020-08-06 22:45:51 -07:00
işlemeyi yapan: Gerrit - the friendly Code Review server
işleme faf4a8b1c8
10 değiştirilmiş dosya ile 605 ekleme ve 39 silme

Dosyayı Görüntüle

@@ -80,6 +80,10 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
ctrl->ops.schedule_dma_cmd = NULL;
ctrl->ops.kickoff_command_non_embedded_mode = NULL;
ctrl->ops.config_clk_gating = NULL;
ctrl->ops.configure_cmddma_window = NULL;
ctrl->ops.reset_trig_ctrl = NULL;
ctrl->ops.map_mdp_regs = NULL;
ctrl->ops.log_line_count = NULL;
break;
case DSI_CTRL_VERSION_2_0:
ctrl->ops.setup_lane_map = dsi_ctrl_hw_20_setup_lane_map;
@@ -95,6 +99,10 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
ctrl->ops.schedule_dma_cmd = NULL;
ctrl->ops.kickoff_command_non_embedded_mode = NULL;
ctrl->ops.config_clk_gating = NULL;
ctrl->ops.configure_cmddma_window = NULL;
ctrl->ops.reset_trig_ctrl = NULL;
ctrl->ops.map_mdp_regs = NULL;
ctrl->ops.log_line_count = NULL;
break;
case DSI_CTRL_VERSION_2_2:
case DSI_CTRL_VERSION_2_3:
@@ -116,6 +124,12 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
ctrl->ops.schedule_dma_cmd = dsi_ctrl_hw_22_schedule_dma_cmd;
ctrl->ops.kickoff_command_non_embedded_mode =
dsi_ctrl_hw_kickoff_non_embedded_mode;
ctrl->ops.configure_cmddma_window =
dsi_ctrl_hw_22_configure_cmddma_window;
ctrl->ops.reset_trig_ctrl =
dsi_ctrl_hw_22_reset_trigger_controls;
ctrl->ops.map_mdp_regs = dsi_ctrl_hw_22_map_mdp_regs;
ctrl->ops.log_line_count = dsi_ctrl_hw_22_log_line_count;
break;
default:
break;

Dosyayı Görüntüle

@@ -274,4 +274,13 @@ void dsi_phy_hw_v4_0_dyn_refresh_pipe_delay(struct dsi_phy_hw *phy,
int dsi_phy_hw_v4_0_cache_phy_timings(struct dsi_phy_per_lane_cfgs *timings,
u32 *dst, u32 size);
void dsi_ctrl_hw_22_configure_cmddma_window(struct dsi_ctrl_hw *ctrl,
struct dsi_ctrl_cmd_dma_info *cmd,
u32 line_no, u32 window);
void dsi_ctrl_hw_22_reset_trigger_controls(struct dsi_ctrl_hw *ctrl,
struct dsi_host_common_cfg *cfg);
int dsi_ctrl_hw_22_map_mdp_regs(struct platform_device *pdev,
struct dsi_ctrl_hw *ctrl);
u32 dsi_ctrl_hw_22_log_line_count(struct dsi_ctrl_hw *ctrl, bool cmd_mode);
#endif /* _DSI_CATALOG_H_ */

Dosyayı Görüntüle

@@ -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",
@@ -1177,6 +1258,60 @@ int dsi_message_validate_tx_mode(struct dsi_ctrl *dsi_ctrl,
return rc;
}
static void dsi_configure_command_scheduling(struct dsi_ctrl *dsi_ctrl,
struct dsi_ctrl_cmd_dma_info *cmd_mem)
{
u32 line_no = 0, window = 0, sched_line_no = 0;
struct dsi_ctrl_hw_ops dsi_hw_ops = dsi_ctrl->hw.ops;
struct dsi_mode_info *timing = &(dsi_ctrl->host_config.video_timing);
line_no = dsi_ctrl->host_config.common_config.dma_sched_line;
window = dsi_ctrl->host_config.common_config.dma_sched_window;
SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_ENTRY, line_no, window);
/*
* In case of command scheduling in video mode, the line at which
* the command is scheduled can revert to the default value i.e. 1
* for the following cases:
* 1) No schedule line defined by the panel.
* 2) schedule line defined is greater than VFP.
*/
if ((dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) &&
dsi_hw_ops.schedule_dma_cmd &&
(dsi_ctrl->current_state.vid_engine_state ==
DSI_CTRL_ENGINE_ON)) {
sched_line_no = (line_no == 0) ? 1 : line_no;
if (timing) {
if (sched_line_no >= timing->v_front_porch)
sched_line_no = 1;
sched_line_no += timing->v_back_porch +
timing->v_sync_width + timing->v_active;
}
dsi_hw_ops.schedule_dma_cmd(&dsi_ctrl->hw, sched_line_no);
}
/*
* In case of command scheduling in command mode, the window size
* is reset to zero, if the total scheduling window is greater
* than the panel height.
*/
if ((dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) &&
dsi_hw_ops.configure_cmddma_window) {
sched_line_no = line_no;
if ((sched_line_no + window) > timing->v_active)
window = 0;
sched_line_no += timing->v_active;
dsi_hw_ops.configure_cmddma_window(&dsi_ctrl->hw, cmd_mem,
sched_line_no, window);
}
SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_EXIT,
sched_line_no, window);
}
static void dsi_kickoff_msg_tx(struct dsi_ctrl *dsi_ctrl,
const struct mipi_dsi_msg *msg,
struct dsi_ctrl_cmd_dma_fifo_info *cmd,
@@ -1184,27 +1319,20 @@ static void dsi_kickoff_msg_tx(struct dsi_ctrl *dsi_ctrl,
u32 flags)
{
u32 hw_flags = 0;
u32 line_no = 0x1;
struct dsi_mode_info *timing;
struct dsi_ctrl_hw_ops dsi_hw_ops = dsi_ctrl->hw.ops;
SDE_EVT32(dsi_ctrl->cell_index, SDE_EVTLOG_FUNC_ENTRY, flags);
if (dsi_ctrl->hw.reset_trig_ctrl)
dsi_hw_ops.reset_trig_ctrl(&dsi_ctrl->hw,
&dsi_ctrl->host_config.common_config);
/* check if custom dma scheduling line needed */
if ((dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) &&
(flags & DSI_CTRL_CMD_CUSTOM_DMA_SCHED))
line_no = dsi_ctrl->host_config.u.video_engine.dma_sched_line;
timing = &(dsi_ctrl->host_config.video_timing);
if (timing)
line_no += timing->v_back_porch + timing->v_sync_width +
timing->v_active;
if ((dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) &&
dsi_hw_ops.schedule_dma_cmd &&
(dsi_ctrl->current_state.vid_engine_state ==
DSI_CTRL_ENGINE_ON))
dsi_hw_ops.schedule_dma_cmd(&dsi_ctrl->hw,
line_no);
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;
@@ -1259,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,
@@ -1921,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);
@@ -2584,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);
@@ -3191,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)) {
@@ -3207,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,

Dosyayı Görüntüle

@@ -229,6 +229,19 @@ struct dsi_ctrl_interrupts {
* insert null packet.
* @modeupdated: Boolean to send new roi if mode is updated.
* @split_link_supported: Boolean to check if hw supports split link.
* @enable_cmd_dma_stats: Boolean to indicate the verbose logging during
* CMD transfer.
* count.
* @cmd_mode: Boolean to indicate if panel is running in
* command mode.
* @cmd_trigger_line: unsigned integer that indicates the line at
* which command gets triggered.
* @cmd_trigger_frame: unsigned integer that indicates the frame at
* which command gets triggered.
* @cmd_success_line: unsigned integer that indicates the line at
* which command transfer is successful.
* @cmd_success_frame: unsigned integer that indicates the frame at
* which command transfer is successful.
*/
struct dsi_ctrl {
struct platform_device *pdev;
@@ -289,6 +302,12 @@ struct dsi_ctrl {
bool null_insertion_enabled;
bool modeupdated;
bool split_link_supported;
bool enable_cmd_dma_stats;
bool cmd_mode;
u32 cmd_trigger_line;
u32 cmd_trigger_frame;
u32 cmd_success_line;
u32 cmd_success_frame;
};
/**

Dosyayı Görüntüle

@@ -831,6 +831,41 @@ struct dsi_ctrl_hw_ops {
* @sel_phy: Bool to control whether to select phy or controller
*/
void (*hs_req_sel)(struct dsi_ctrl_hw *ctrl, bool sel_phy);
/**
* hw.ops.configure_cmddma_window() - configure DMA window for CMD TX
* @ctrl: Pointer to the controller host hardware.
* @cmd: Pointer to the DSI DMA command info.
* @line_no: Line number at which the CMD needs to be triggered.
* @window: Width of the DMA CMD window.
*/
void (*configure_cmddma_window)(struct dsi_ctrl_hw *ctrl,
struct dsi_ctrl_cmd_dma_info *cmd,
u32 line_no, u32 window);
/**
* hw.ops.reset_trig_ctrl() - resets trigger control of DSI controller
* @ctrl: Pointer to the controller host hardware.
* @cfg: Common configuration parameters.
*/
void (*reset_trig_ctrl)(struct dsi_ctrl_hw *ctrl,
struct dsi_host_common_cfg *cfg);
/**
* hw.ops.map_mdp_regs() - maps MDP interface line count registers.
* @pdev: Pointer to platform device.
* @ctrl: Pointer to the controller host hardware.
*/
int (*map_mdp_regs)(struct platform_device *pdev,
struct dsi_ctrl_hw *ctrl);
/**
* hw.ops.log_line_count() - reads the MDP interface line count
* registers.
* @ctrl: Pointer to the controller host hardware.
* @cmd_mode: Boolean to indicate command mode operation.
*/
u32 (*log_line_count)(struct dsi_ctrl_hw *ctrl, bool cmd_mode);
};
/*
@@ -841,6 +876,13 @@ struct dsi_ctrl_hw_ops {
* @mmss_misc_length: Length of mmss_misc register map.
* @disp_cc_base: Base address of disp_cc register map.
* @disp_cc_length: Length of disp_cc register map.
* @te_rd_ptr_reg: Address of MDP_TEAR_INTF_TEAR_LINE_COUNT. This
* register is used for testing and validating the RD
* ptr value when a CMD is triggered and it succeeds.
* @line_count_reg: Address of MDP_TEAR_INTF_LINE_COUNT. This
* register is used for testing and validating the
* line count value when a CMD is triggered and it
* succeeds.
* @index: Instance ID of the controller.
* @feature_map: Features supported by the DSI controller.
* @ops: Function pointers to the operations supported by the
@@ -852,6 +894,8 @@ struct dsi_ctrl_hw_ops {
* @null_insertion_enabled: A boolean property to allow dsi controller to
* insert null packet.
* @widebus_support: 48 bit wide data bus is supported.
* @reset_trig_ctrl: Boolean to indicate if trigger control needs to
* be reset to default.
*/
struct dsi_ctrl_hw {
void __iomem *base;
@@ -859,6 +903,8 @@ struct dsi_ctrl_hw {
void __iomem *mmss_misc_base;
u32 mmss_misc_length;
void __iomem *disp_cc_base;
void __iomem *te_rd_ptr_reg;
void __iomem *line_count_reg;
u32 disp_cc_length;
u32 index;
@@ -873,6 +919,7 @@ struct dsi_ctrl_hw {
bool phy_isolation_enabled;
bool null_insertion_enabled;
bool widebus_support;
bool reset_trig_ctrl;
};
#endif /* _DSI_CTRL_HW_H_ */

Dosyayı Görüntüle

@@ -12,6 +12,13 @@
/* register to configure DMA scheduling */
#define DSI_DMA_SCHEDULE_CTRL 0x100
#define DSI_DMA_SCHEDULE_CTRL2 0x0104
/* MDP INTF registers to be mapped for debug feature*/
#define MDP_INTF1_TEAR_LINE_COUNT 0xAE36298
#define MDP_INTF2_TEAR_LINE_COUNT 0xAE37298
#define MDP_INTF1_LINE_COUNT 0xAE360B0
#define MDP_INTF2_LINE_COUNT 0xAE370B0
void dsi_ctrl_hw_22_setup_lane_map(struct dsi_ctrl_hw *ctrl,
struct dsi_lane_map *lane_map)
@@ -102,6 +109,7 @@ void dsi_ctrl_hw_22_schedule_dma_cmd(struct dsi_ctrl_hw *ctrl, int line_no)
reg |= (line_no & 0xffff);
DSI_W32(ctrl, DSI_DMA_SCHEDULE_CTRL, reg);
ctrl->reset_trig_ctrl = true;
}
/*
@@ -181,3 +189,149 @@ void dsi_ctrl_hw_22_config_clk_gating(struct dsi_ctrl_hw *ctrl, bool enable,
DSI_DISP_CC_W32(ctrl, DISP_CC_MISC_CMD_REG_OFF, reg);
}
/**
* dsi_ctrl_hw_22_configure_cmddma_window() - configure DMA window for CMD TX
* @ctrl: Pointer to the controller host hardware.
* @cmd: Pointer to the DSI DMA command info.
* @line_no: Line number at which the CMD needs to be triggered.
* @window: Width of the DMA CMD window.
*/
void dsi_ctrl_hw_22_configure_cmddma_window(struct dsi_ctrl_hw *ctrl,
struct dsi_ctrl_cmd_dma_info *cmd,
u32 line_no, u32 window)
{
u32 reg = 0;
if (!window)
return;
if (cmd->en_broadcast) {
reg = DSI_R32(ctrl, DSI_TRIG_CTRL);
if (cmd->is_master) {
reg &= ~0xF;
reg |= 0xc;
} else {
reg &= ~0xF;
reg |= BIT(16);
}
DSI_W32(ctrl, DSI_TRIG_CTRL, reg);
if (cmd->is_master) {
reg = 0;
reg |= line_no;
reg |= window << 16;
DSI_W32(ctrl, DSI_DMA_SCHEDULE_CTRL2, reg);
}
} else {
reg = DSI_R32(ctrl, DSI_TRIG_CTRL);
reg &= ~0xF;
reg |= 0xc;
DSI_W32(ctrl, DSI_TRIG_CTRL, reg);
reg = 0;
reg |= line_no;
reg |= window << 16;
DSI_W32(ctrl, DSI_DMA_SCHEDULE_CTRL2, reg);
}
ctrl->reset_trig_ctrl = true;
}
/**
* dsi_ctrl_hw_22_reset_trigger_controls() - reset dsi trigger configurations
* @ctrl: Pointer to the controller host hardware.
* @cfg: DSI host configuration that is common to both video and
* command modes.
*/
void dsi_ctrl_hw_22_reset_trigger_controls(struct dsi_ctrl_hw *ctrl,
struct dsi_host_common_cfg *cfg)
{
u32 reg = 0;
const u8 trigger_map[DSI_TRIGGER_MAX] = {
0x0, 0x2, 0x1, 0x4, 0x5, 0x6 };
reg |= (cfg->te_mode == DSI_TE_ON_EXT_PIN) ? BIT(31) : 0;
reg |= (trigger_map[cfg->dma_cmd_trigger] & 0x7);
reg |= (trigger_map[cfg->mdp_cmd_trigger] & 0x7) << 4;
DSI_W32(ctrl, DSI_TRIG_CTRL, reg);
DSI_W32(ctrl, DSI_DMA_SCHEDULE_CTRL2, 0x0);
DSI_W32(ctrl, DSI_DMA_SCHEDULE_CTRL, 0x0);
ctrl->reset_trig_ctrl = false;
}
/**
* dsi_ctrl_hw_22_map_mdp_regs() - maps MDP interface line count registers.
* @pdev: Pointer to platform device.
* @ctrl: Pointer to the controller host hardware.
*
* Return: 0 on success and error on failure.
*/
int dsi_ctrl_hw_22_map_mdp_regs(struct platform_device *pdev,
struct dsi_ctrl_hw *ctrl)
{
int rc = 0;
void __iomem *ptr = NULL, *ptr1 = NULL;
if (ctrl->index == 0) {
ptr = devm_ioremap(&pdev->dev, MDP_INTF1_TEAR_LINE_COUNT, 1);
if (IS_ERR_OR_NULL(ptr)) {
DSI_CTRL_HW_ERR(ctrl,
"MDP TE LINE COUNT address not found\n");
rc = PTR_ERR(ptr);
return rc;
}
ptr1 = devm_ioremap(&pdev->dev, MDP_INTF1_LINE_COUNT, 1);
if (IS_ERR_OR_NULL(ptr1)) {
DSI_CTRL_HW_ERR(ctrl,
"MDP TE LINE COUNT address not found\n");
rc = PTR_ERR(ptr1);
return rc;
}
}
if (ctrl->index == 1) {
ptr = devm_ioremap(&pdev->dev, MDP_INTF2_TEAR_LINE_COUNT, 1);
if (IS_ERR_OR_NULL(ptr)) {
DSI_CTRL_HW_ERR(ctrl,
"MDP TE LINE COUNT address not found\n");
rc = PTR_ERR(ptr);
return rc;
}
ptr1 = devm_ioremap(&pdev->dev, MDP_INTF2_LINE_COUNT, 1);
if (IS_ERR_OR_NULL(ptr1)) {
DSI_CTRL_HW_ERR(ctrl,
"MDP TE LINE COUNT address not found\n");
rc = PTR_ERR(ptr1);
return rc;
}
}
ctrl->te_rd_ptr_reg = ptr;
ctrl->line_count_reg = ptr1;
return rc;
}
/**
* dsi_ctrl_hw_22_log_line_count() - reads the MDP interface line count
* registers.
* @ctrl: Pointer to the controller host hardware.
* @cmd_mode: Boolean to indicate command mode operation.
*
* Return: INTF register value.
*/
u32 dsi_ctrl_hw_22_log_line_count(struct dsi_ctrl_hw *ctrl, bool cmd_mode)
{
u32 reg = 0;
if (cmd_mode && ctrl->te_rd_ptr_reg)
reg = readl_relaxed(ctrl->te_rd_ptr_reg);
else if (ctrl->line_count_reg)
reg = readl_relaxed(ctrl->line_count_reg);
return reg;
}

Dosyayı Görüntüle

@@ -472,6 +472,11 @@ struct dsi_split_link_config {
* @phy_type: DPHY/CPHY is enabled for this panel.
* @dsi_split_link_config: Split Link Configuration.
* @byte_intf_clk_div: Determines the factor for calculating byte intf clock.
* @dma_sched_line: Line at which dma command gets triggered. In case of
* video mode it is the line number after vactive and for
* cmd it points to the line after TE.
* @dma_sched_window: Determines the width of the window during the
* DSI command will be sent by the HW.
*/
struct dsi_host_common_cfg {
enum dsi_pixel_format dst_format;
@@ -497,6 +502,8 @@ struct dsi_host_common_cfg {
enum dsi_phy_type phy_type;
struct dsi_split_link_config split_link;
u32 byte_intf_clk_div;
u32 dma_sched_line;
u32 dma_sched_window;
};
/**
@@ -513,8 +520,6 @@ struct dsi_host_common_cfg {
* @bllp_lp11_en: Enter low power stop mode (LP-11) during BLLP.
* @traffic_mode: Traffic mode for video stream.
* @vc_id: Virtual channel identifier.
* @dma_sched_line: Line number, after vactive end, at which command dma
* needs to be triggered.
*/
struct dsi_video_engine_cfg {
bool last_line_interleave_en;
@@ -526,7 +531,6 @@ struct dsi_video_engine_cfg {
bool bllp_lp11_en;
enum dsi_video_traffic_mode traffic_mode;
u32 vc_id;
u32 dma_sched_line;
};
/**

Dosyayı Görüntüle

@@ -673,8 +673,10 @@ static int dsi_display_read_status(struct dsi_display_ctrl *ctrl,
lenp = config->status_valid_params ?: config->status_cmds_rlen;
count = config->status_cmd.count;
cmds = config->status_cmd.cmds;
flags |= (DSI_CTRL_CMD_FETCH_MEMORY | DSI_CTRL_CMD_READ |
DSI_CTRL_CMD_CUSTOM_DMA_SCHED);
flags |= (DSI_CTRL_CMD_FETCH_MEMORY | DSI_CTRL_CMD_READ);
if (ctrl->ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE)
flags |= DSI_CTRL_CMD_CUSTOM_DMA_SCHED;
for (i = 0; i < count; ++i) {
memset(config->status_buf, 0x0, SZ_4K);
@@ -682,6 +684,10 @@ static int dsi_display_read_status(struct dsi_display_ctrl *ctrl,
cmds[i].msg.flags |= MIPI_DSI_MSG_LASTCOMMAND;
flags |= DSI_CTRL_CMD_LAST_COMMAND;
}
if ((cmds[i].msg.flags & MIPI_DSI_MSG_CMD_DMA_SCHED) &&
(panel->panel_initialized))
flags |= DSI_CTRL_CMD_CUSTOM_DMA_SCHED;
if (config->status_cmd.state == DSI_CMD_SET_STATE_LP)
cmds[i].msg.flags |= MIPI_DSI_MSG_USE_LPM;
cmds[i].msg.rx_buf = config->status_buf;
@@ -916,6 +922,9 @@ static int dsi_display_cmd_prepare(const char *cmd_buf, u32 cmd_buf_len,
return -EINVAL;
}
if (cmd->last_command)
cmd->msg.flags |= MIPI_DSI_MSG_LASTCOMMAND;
for (i = 0; i < cmd->msg.tx_len; i++)
payload[i] = cmd_buf[7 + i];
@@ -972,8 +981,12 @@ static int dsi_display_cmd_rx(struct dsi_display *display,
goto error;
}
flags |= (DSI_CTRL_CMD_FETCH_MEMORY | DSI_CTRL_CMD_READ |
DSI_CTRL_CMD_CUSTOM_DMA_SCHED);
flags |= (DSI_CTRL_CMD_FETCH_MEMORY | DSI_CTRL_CMD_READ);
if ((m_ctrl->ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) ||
((cmd->msg.flags & MIPI_DSI_MSG_CMD_DMA_SCHED) &&
(display->panel->panel_initialized)))
flags |= DSI_CTRL_CMD_CUSTOM_DMA_SCHED;
rc = dsi_ctrl_cmd_transfer(m_ctrl->ctrl, &cmd->msg, &flags);
if (rc <= 0)
DSI_ERR("rx cmd transfer failed rc = %d\n", rc);
@@ -1617,6 +1630,107 @@ error:
return len;
}
static ssize_t debugfs_update_cmd_scheduling_params(struct file *file,
const char __user *user_buf,
size_t user_len,
loff_t *ppos)
{
struct dsi_display *display = file->private_data;
struct dsi_display_ctrl *display_ctrl;
char *buf;
int rc = 0;
u32 line = 0, window = 0;
size_t len;
int i;
if (!display)
return -ENODEV;
if (*ppos)
return 0;
buf = kzalloc(256, GFP_KERNEL);
if (ZERO_OR_NULL_PTR(buf))
return -ENOMEM;
len = min_t(size_t, user_len, 255);
if (copy_from_user(buf, user_buf, len)) {
rc = -EINVAL;
goto error;
}
buf[len] = '\0'; /* terminate the string */
if (sscanf(buf, "%d %d", &line, &window) != 2)
return -EFAULT;
display_for_each_ctrl(i, display) {
struct dsi_ctrl *ctrl;
display_ctrl = &display->ctrl[i];
if (!display_ctrl->ctrl)
continue;
ctrl = display_ctrl->ctrl;
ctrl->host_config.common_config.dma_sched_line = line;
ctrl->host_config.common_config.dma_sched_window = window;
}
rc = len;
error:
kfree(buf);
return rc;
}
static ssize_t debugfs_read_cmd_scheduling_params(struct file *file,
char __user *user_buf,
size_t user_len,
loff_t *ppos)
{
struct dsi_display *display = file->private_data;
struct dsi_display_ctrl *m_ctrl;
struct dsi_ctrl *ctrl;
char *buf;
u32 len = 0;
int rc = 0;
size_t max_len = min_t(size_t, user_len, SZ_4K);
if (!display)
return -ENODEV;
if (*ppos)
return 0;
m_ctrl = &display->ctrl[display->cmd_master_idx];
ctrl = m_ctrl->ctrl;
buf = kzalloc(max_len, GFP_KERNEL);
if (ZERO_OR_NULL_PTR(buf))
return -ENOMEM;
len += scnprintf(buf, max_len, "Schedule command window start: %d\n",
ctrl->host_config.common_config.dma_sched_line);
len += scnprintf((buf + len), max_len - len,
"Schedule command window width: %d\n",
ctrl->host_config.common_config.dma_sched_window);
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 dump_info_fops = {
.open = simple_open,
.read = debugfs_dump_info_read,
@@ -1639,6 +1753,12 @@ static const struct file_operations esd_check_mode_fops = {
.read = debugfs_read_esd_check_mode,
};
static const struct file_operations dsi_command_scheduling_fops = {
.open = simple_open,
.write = debugfs_update_cmd_scheduling_params,
.read = debugfs_read_cmd_scheduling_params,
};
static int dsi_display_debugfs_init(struct dsi_display *display)
{
int rc = 0;
@@ -1690,6 +1810,18 @@ static int dsi_display_debugfs_init(struct dsi_display *display)
goto error_remove_dir;
}
dump_file = debugfs_create_file("cmd_sched_params",
0644,
dir,
display,
&dsi_command_scheduling_fops);
if (IS_ERR_OR_NULL(dump_file)) {
rc = PTR_ERR(dump_file);
DSI_ERR("[%s] debugfs for cmd scheduling file failed, rc=%d\n",
display->name, rc);
goto error_remove_dir;
}
misr_data = debugfs_create_file("misr_data",
0600,
dir,
@@ -2855,6 +2987,12 @@ static int dsi_display_broadcast_cmd(struct dsi_display *display,
m_flags |= DSI_CTRL_CMD_LAST_COMMAND;
}
if ((msg->flags & MIPI_DSI_MSG_CMD_DMA_SCHED) &&
(display->panel->panel_initialized)) {
flags |= DSI_CTRL_CMD_CUSTOM_DMA_SCHED;
m_flags |= DSI_CTRL_CMD_CUSTOM_DMA_SCHED;
}
if (display->queue_cmd_waits ||
msg->flags & MIPI_DSI_MSG_ASYNC_OVERRIDE) {
flags |= DSI_CTRL_CMD_ASYNC_WAIT;
@@ -3023,6 +3161,10 @@ static ssize_t dsi_host_transfer(struct mipi_dsi_host *host,
msg->flags & MIPI_DSI_MSG_ASYNC_OVERRIDE)
cmd_flags |= DSI_CTRL_CMD_ASYNC_WAIT;
if ((msg->flags & MIPI_DSI_MSG_CMD_DMA_SCHED) &&
(display->panel->panel_initialized))
cmd_flags |= DSI_CTRL_CMD_CUSTOM_DMA_SCHED;
rc = dsi_ctrl_cmd_transfer(display->ctrl[ctrl_idx].ctrl, msg,
&cmd_flags);
if (rc) {

Dosyayı Görüntüle

@@ -1061,7 +1061,7 @@ static int dsi_panel_parse_misc_host_config(struct dsi_host_common_cfg *host,
struct dsi_parser_utils *utils,
const char *name)
{
u32 val = 0;
u32 val = 0, line_no = 0, window = 0;
int rc = 0;
bool panel_cphy_mode = false;
@@ -1094,6 +1094,22 @@ static int dsi_panel_parse_misc_host_config(struct dsi_host_common_cfg *host,
host->phy_type = panel_cphy_mode ? DSI_PHY_TYPE_CPHY
: DSI_PHY_TYPE_DPHY;
rc = utils->read_u32(utils->data, "qcom,mdss-dsi-dma-schedule-line",
&line_no);
if (rc)
host->dma_sched_line = 0;
else
host->dma_sched_line = line_no;
rc = utils->read_u32(utils->data, "qcom,mdss-dsi-dma-schedule-window",
&window);
if (rc)
host->dma_sched_window = 0;
else
host->dma_sched_window = window;
DSI_DEBUG("[%s] DMA scheduling parameters Line: %d Window: %d\n", name,
host->dma_sched_line, host->dma_sched_window);
return 0;
}
@@ -1354,7 +1370,6 @@ static int dsi_panel_parse_video_host_config(struct dsi_video_engine_cfg *cfg,
const char *traffic_mode;
u32 vc_id = 0;
u32 val = 0;
u32 line_no = 0;
rc = utils->read_u32(utils->data, "qcom,mdss-dsi-h-sync-pulse", &val);
if (rc) {
@@ -1417,17 +1432,6 @@ static int dsi_panel_parse_video_host_config(struct dsi_video_engine_cfg *cfg,
cfg->vc_id = vc_id;
}
rc = utils->read_u32(utils->data, "qcom,mdss-dsi-dma-schedule-line",
&line_no);
if (rc) {
DSI_DEBUG("[%s] set default dma scheduling line no\n", name);
cfg->dma_sched_line = 0x1;
/* do not fail since we have default value */
rc = 0;
} else {
cfg->dma_sched_line = line_no;
}
error:
return rc;
}
@@ -1679,7 +1683,7 @@ static int dsi_panel_create_cmd_packets(const char *data,
cmd[i].msg.type = data[0];
cmd[i].last_command = (data[1] == 1);
cmd[i].msg.channel = data[2];
cmd[i].msg.flags |= (data[3] == 1 ? MIPI_DSI_MSG_REQ_ACK : 0);
cmd[i].msg.flags |= data[3];
cmd[i].msg.ctrl = 0;
cmd[i].post_wait_ms = cmd[i].msg.wait_ms = data[4];
cmd[i].msg.tx_len = ((data[5] << 8) | (data[6]));

Dosyayı Görüntüle

@@ -35,6 +35,7 @@
* Override to use async transfer
*/
#define MIPI_DSI_MSG_ASYNC_OVERRIDE BIT(4)
#define MIPI_DSI_MSG_CMD_DMA_SCHED BIT(5)
enum dsi_panel_rotation {
DSI_PANEL_ROTATE_NONE = 0,