drm/msm/dsi-staging: add support for command mode panels
Add support for command mode panels. Command engine state must be
ref-counted since it is toggled in two paths, command transfer and mdp
command frame updates.
Change-Id: I9aba97465ad822c4c862f6aa5422dc47cb6664c8
Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
index 114998f..3f698cb 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
@@ -28,6 +28,7 @@
ctrl->ops.video_engine_setup = dsi_ctrl_hw_14_video_engine_setup;
ctrl->ops.set_video_timing = dsi_ctrl_hw_14_set_video_timing;
ctrl->ops.cmd_engine_setup = dsi_ctrl_hw_14_cmd_engine_setup;
+ ctrl->ops.setup_cmd_stream = dsi_ctrl_hw_14_setup_cmd_stream;
ctrl->ops.ctrl_en = dsi_ctrl_hw_14_ctrl_en;
ctrl->ops.cmd_engine_en = dsi_ctrl_hw_14_cmd_engine_en;
ctrl->ops.phy_sw_reset = dsi_ctrl_hw_14_phy_sw_reset;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
index e4b33c2..506fa28 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
@@ -75,6 +75,11 @@
void dsi_ctrl_hw_14_ctrl_en(struct dsi_ctrl_hw *ctrl, bool on);
void dsi_ctrl_hw_14_cmd_engine_en(struct dsi_ctrl_hw *ctrl, bool on);
+void dsi_ctrl_hw_14_setup_cmd_stream(struct dsi_ctrl_hw *ctrl,
+ u32 width_in_pixels,
+ u32 h_stride,
+ u32 height_in_lines,
+ u32 vc_id);
void dsi_ctrl_hw_14_phy_sw_reset(struct dsi_ctrl_hw *ctrl);
void dsi_ctrl_hw_14_soft_reset(struct dsi_ctrl_hw *ctrl);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index a282fce..381827e 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -1485,23 +1485,30 @@
goto error;
}
- dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw,
- &dsi_ctrl->host_config.video_timing);
-
dsi_ctrl->hw.ops.setup_lane_map(&dsi_ctrl->hw,
&dsi_ctrl->host_config.lane_map);
dsi_ctrl->hw.ops.host_setup(&dsi_ctrl->hw,
&dsi_ctrl->host_config.common_config);
- if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE)
+ if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) {
dsi_ctrl->hw.ops.cmd_engine_setup(&dsi_ctrl->hw,
&dsi_ctrl->host_config.common_config,
&dsi_ctrl->host_config.u.cmd_engine);
- else
+
+ dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw,
+ dsi_ctrl->host_config.video_timing.h_active,
+ dsi_ctrl->host_config.video_timing.h_active * 3,
+ dsi_ctrl->host_config.video_timing.v_active,
+ 0x0);
+ } else {
dsi_ctrl->hw.ops.video_engine_setup(&dsi_ctrl->hw,
&dsi_ctrl->host_config.common_config,
&dsi_ctrl->host_config.u.video_engine);
+ dsi_ctrl->hw.ops.set_video_timing(&dsi_ctrl->hw,
+ &dsi_ctrl->host_config.video_timing);
+ }
+
dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
index b5ddfbb..a33d6d3 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
@@ -272,6 +272,22 @@
struct dsi_cmd_engine_cfg *cfg);
/**
+ * setup_cmd_stream() - set up parameters for command pixel streams
+ * @ctrl: Pointer to controller host hardware.
+ * @width_in_pixels: Width of the stream in pixels.
+ * @h_stride: Horizontal stride in bytes.
+ * @height_inLines: Number of lines in the stream.
+ * @vc_id: stream_id.
+ *
+ * Setup parameters for command mode pixel stream size.
+ */
+ void (*setup_cmd_stream)(struct dsi_ctrl_hw *ctrl,
+ u32 width_in_pixels,
+ u32 h_stride,
+ u32 height_in_lines,
+ u32 vc_id);
+
+ /**
* ctrl_en() - enable DSI controller engine
* @ctrl: Pointer to the controller host hardware.
* @on: turn on/off the DSI controller engine.
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c
index 8326024..9d819a2 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c
@@ -85,9 +85,6 @@
DSI_W32(ctrl, DSI_CTRL, reg_value);
- /* Enable Timing double buffering */
- DSI_W32(ctrl, DSI_DSI_TIMING_DB_MODE, 0x1);
-
pr_debug("[DSI_%d]Host configuration complete\n", ctrl->index);
}
@@ -198,6 +195,35 @@
}
/**
+ * setup_cmd_stream() - set up parameters for command pixel streams
+ * @ctrl: Pointer to controller host hardware.
+ * @width_in_pixels: Width of the stream in pixels.
+ * @h_stride: Horizontal stride in bytes.
+ * @height_inLines: Number of lines in the stream.
+ * @vc_id: stream_id
+ *
+ * Setup parameters for command mode pixel stream size.
+ */
+void dsi_ctrl_hw_14_setup_cmd_stream(struct dsi_ctrl_hw *ctrl,
+ u32 width_in_pixels,
+ u32 h_stride,
+ u32 height_in_lines,
+ u32 vc_id)
+{
+ u32 reg = 0;
+
+ reg = (h_stride + 1) << 16;
+ reg |= (vc_id & 0x3) << 8;
+ reg |= 0x39; /* packet data type */
+ DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM0_CTRL, reg);
+ DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM1_CTRL, reg);
+
+ reg = (height_in_lines << 16) | width_in_pixels;
+ DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM0_TOTAL, reg);
+ DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM1_TOTAL, reg);
+}
+
+/**
* video_engine_setup() - Setup dsi host controller for video mode
* @ctrl: Pointer to controller host hardware.
* @common_cfg: Common configuration parameters.
@@ -229,6 +255,9 @@
reg |= (common_cfg->bit_swap_green ? BIT(4) : 0);
reg |= (common_cfg->bit_swap_blue ? BIT(8) : 0);
DSI_W32(ctrl, DSI_VIDEO_MODE_DATA_CTRL, reg);
+ /* Enable Timing double buffering */
+ DSI_W32(ctrl, DSI_DSI_TIMING_DB_MODE, 0x1);
+
pr_debug("[DSI_%d] Video engine setup done\n", ctrl->index);
}
@@ -255,6 +284,10 @@
reg |= cmd_mode_format_map[common_cfg->dst_format];
DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_CTRL, reg);
+ reg = DSI_R32(ctrl, DSI_COMMAND_MODE_MDP_CTRL2);
+ reg |= BIT(16);
+ DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_CTRL2, reg);
+
reg = cfg->wr_mem_start & 0xFF;
reg |= (cfg->wr_mem_continue & 0xFF) << 8;
reg |= (cfg->insert_dcs_command ? BIT(16) : 0);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 68e3b52..1e2226c0 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -364,6 +364,11 @@
int i;
struct dsi_display_ctrl *m_ctrl, *ctrl;
+ if (display->cmd_engine_refcount > 0) {
+ display->cmd_engine_refcount++;
+ return 0;
+ }
+
m_ctrl = &display->ctrl[display->cmd_master_idx];
rc = dsi_ctrl_set_cmd_engine_state(m_ctrl->ctrl, DSI_CTRL_ENGINE_ON);
@@ -387,6 +392,7 @@
}
}
+ display->cmd_engine_refcount++;
return rc;
error_disable_master:
(void)dsi_ctrl_set_cmd_engine_state(m_ctrl->ctrl, DSI_CTRL_ENGINE_OFF);
@@ -400,6 +406,14 @@
int i;
struct dsi_display_ctrl *m_ctrl, *ctrl;
+ if (display->cmd_engine_refcount == 0) {
+ pr_err("[%s] Invalid refcount\n", display->name);
+ return 0;
+ } else if (display->cmd_engine_refcount > 1) {
+ display->cmd_engine_refcount--;
+ return 0;
+ }
+
m_ctrl = &display->ctrl[display->cmd_master_idx];
for (i = 0; i < display->ctrl_count; i++) {
ctrl = &display->ctrl[i];
@@ -421,6 +435,7 @@
}
error:
+ display->cmd_engine_refcount = 0;
return rc;
}
@@ -1834,20 +1849,33 @@
if (rc) {
pr_err("[%s] failed to enable DSI panel, rc=%d\n",
display->name, rc);
- goto error_disable_vid_engine;
+ goto error;
}
- rc = dsi_display_vid_engine_enable(display);
- if (rc) {
- pr_err("[%s] failed to enable DSI video engine, rc=%d\n",
- display->name, rc);
- goto error;
+ if (display->config.panel_mode == DSI_OP_VIDEO_MODE) {
+ rc = dsi_display_vid_engine_enable(display);
+ if (rc) {
+ pr_err("[%s]failed to enable DSI video engine, rc=%d\n",
+ display->name, rc);
+ goto error_disable_panel;
+ }
+ } else if (display->config.panel_mode == DSI_OP_CMD_MODE) {
+ rc = dsi_display_cmd_engine_enable(display);
+ if (rc) {
+ pr_err("[%s]failed to enable DSI cmd engine, rc=%d\n",
+ display->name, rc);
+ goto error_disable_panel;
+ }
+ } else {
+ pr_err("[%s] Invalid configuration\n", display->name);
+ rc = -EINVAL;
+ goto error_disable_panel;
}
goto error;
-error_disable_vid_engine:
- (void)dsi_display_vid_engine_disable(display);
+error_disable_panel:
+ (void)dsi_panel_disable(display->panel);
error:
mutex_unlock(&display->display_lock);
return rc;
@@ -1914,10 +1942,20 @@
pr_err("[%s] failed to disable DSI panel, rc=%d\n",
display->name, rc);
- rc = dsi_display_vid_engine_disable(display);
- if (rc)
- pr_err("[%s] failed to disable video engine, rc=%d\n",
- display->name, rc);
+ if (display->config.panel_mode == DSI_OP_VIDEO_MODE) {
+ rc = dsi_display_vid_engine_disable(display);
+ if (rc)
+ pr_err("[%s]failed to disable DSI vid engine, rc=%d\n",
+ display->name, rc);
+ } else if (display->config.panel_mode == DSI_OP_CMD_MODE) {
+ rc = dsi_display_cmd_engine_disable(display);
+ if (rc)
+ pr_err("[%s]failed to disable DSI cmd engine, rc=%d\n",
+ display->name, rc);
+ } else {
+ pr_err("[%s] Invalid configuration\n", display->name);
+ rc = -EINVAL;
+ }
mutex_unlock(&display->display_lock);
return rc;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
index df15bb8..1897ce3 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
@@ -101,10 +101,6 @@
u32 dsi_ctrl_idx;
enum dsi_power_state power_state;
- bool cmd_engine_enabled;
- bool video_engine_enabled;
- bool ulps_enabled;
- bool clamps_enabled;
/* phy info */
struct msm_dsi_phy *phy;
@@ -182,6 +178,7 @@
struct mipi_dsi_host host;
struct dsi_connector *connector;
struct dsi_bridge *bridge;
+ u32 cmd_engine_refcount;
};
int dsi_display_dev_probe(struct platform_device *pdev);