Merge "disp: msm: dsi: add debug ability to read TE read pointer line count"
Bu işleme şunda yer alıyor:

işlemeyi yapan:
Gerrit - the friendly Code Review server

işleme
faf4a8b1c8
@@ -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;
|
||||
|
@@ -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_ */
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -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_ */
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -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) {
|
||||
|
@@ -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]));
|
||||
|
@@ -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,
|
||||
|
Yeni konuda referans
Bir kullanıcı engelle