drm: msm: dsi-staging: Add support for cmd fetch from AXI bus
Certain panels have commands exceeding 64 bytes and FIFO TPG
cannot handle this requirement. This change adds support for
fetching commands over AXI bus which addresses sending
commands greater than 64 bytes
Change-Id: I125f60066871bb0a1c9ed8264ca688a6dd21b637
Signed-off-by: Shashank Babu Chinta Venkata <sbchin@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index 39b797e..da7a7c0 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -879,14 +879,12 @@
int rc = 0;
struct mipi_dsi_packet packet;
struct dsi_ctrl_cmd_dma_fifo_info cmd;
+ struct dsi_ctrl_cmd_dma_info cmd_mem;
u32 hw_flags = 0;
u32 length = 0;
u8 *buffer = NULL;
-
- if (!(flags & DSI_CTRL_CMD_FIFO_STORE)) {
- pr_err("Memory DMA is not supported, use FIFO\n");
- goto error;
- }
+ u32 cnt = 0;
+ u8 *cmdbuf;
rc = mipi_dsi_create_packet(&packet, msg);
if (rc) {
@@ -894,7 +892,32 @@
goto error;
}
- if (flags & DSI_CTRL_CMD_FIFO_STORE) {
+ if (flags & DSI_CTRL_CMD_FETCH_MEMORY) {
+ rc = dsi_ctrl_copy_and_pad_cmd(dsi_ctrl,
+ &packet,
+ &buffer,
+ &length);
+
+ if (rc) {
+ pr_err("[%s] failed to copy message, rc=%d\n",
+ dsi_ctrl->name, rc);
+ goto error;
+ }
+
+ cmd_mem.offset = dsi_ctrl->cmd_buffer_iova;
+ cmd_mem.length = length;
+ cmd_mem.en_broadcast = (flags & DSI_CTRL_CMD_BROADCAST) ?
+ true : false;
+ cmd_mem.is_master = (flags & DSI_CTRL_CMD_BROADCAST_MASTER) ?
+ true : false;
+ cmd_mem.use_lpm = (msg->flags & MIPI_DSI_MSG_USE_LPM) ?
+ true : false;
+
+ cmdbuf = (u8 *)(dsi_ctrl->vaddr);
+ for (cnt = 0; cnt < length; cnt++)
+ cmdbuf[cnt] = buffer[cnt];
+
+ } else if (flags & DSI_CTRL_CMD_FIFO_STORE) {
rc = dsi_ctrl_copy_and_pad_cmd(dsi_ctrl,
&packet,
&buffer,
@@ -920,10 +943,15 @@
if (!(flags & DSI_CTRL_CMD_DEFER_TRIGGER))
reinit_completion(&dsi_ctrl->int_info.cmd_dma_done);
- if (flags & DSI_CTRL_CMD_FIFO_STORE)
+ if (flags & DSI_CTRL_CMD_FETCH_MEMORY) {
+ dsi_ctrl->hw.ops.kickoff_command(&dsi_ctrl->hw,
+ &cmd_mem,
+ hw_flags);
+ } else if (flags & DSI_CTRL_CMD_FIFO_STORE) {
dsi_ctrl->hw.ops.kickoff_fifo_command(&dsi_ctrl->hw,
&cmd,
hw_flags);
+ }
if (!(flags & DSI_CTRL_CMD_DEFER_TRIGGER)) {
u32 retry = 10;
@@ -2171,14 +2199,14 @@
}
/**
- * dsi_ctrl_set_ulps() - set ULPS state for DSI lanes.
- * @dsi_ctrl: DSI controller handle.
- * @enable: enable/disable ULPS.
- *
- * ULPS can be enabled/disabled after DSI host engine is turned on.
- *
- * Return: error code.
- */
+ * dsi_ctrl_set_ulps() - set ULPS state for DSI lanes.
+ * @dsi_ctrl: DSI controller handle.
+ * @enable: enable/disable ULPS.
+ *
+ * ULPS can be enabled/disabled after DSI host engine is turned on.
+ *
+ * Return: error code.
+ */
int dsi_ctrl_set_ulps(struct dsi_ctrl *dsi_ctrl, bool enable)
{
int rc = 0;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
index f89cb68..7f36fde 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
@@ -33,12 +33,15 @@
* @DSI_CTRL_CMD_DEFER_TRIGGER: Defer the command trigger to later.
* @DSI_CTRL_CMD_FIFO_STORE: Use FIFO for command transfer in place of
* reading data from memory.
+ * @DSI_CTRL_CMD_FETCH_MEMORY: Fetch command from memory through AXI bus
+ * and transfer it.
*/
#define DSI_CTRL_CMD_READ 0x1
#define DSI_CTRL_CMD_BROADCAST 0x2
#define DSI_CTRL_CMD_BROADCAST_MASTER 0x4
#define DSI_CTRL_CMD_DEFER_TRIGGER 0x8
#define DSI_CTRL_CMD_FIFO_STORE 0x10
+#define DSI_CTRL_CMD_FETCH_MEMORY 0x20
/**
* enum dsi_power_state - defines power states for dsi controller.
@@ -188,6 +191,8 @@
* @roi: Partial update region of interest.
* Origin is top left of this CTRL.
* @tx_cmd_buf: Tx command buffer.
+ * @cmd_buffer_iova: cmd buffer mapped address.
+ * @vaddr: CPU virtual address of cmd buffer.
* @cmd_buffer_size: Size of command buffer.
* @debugfs_root: Root for debugfs entries.
*/
@@ -221,6 +226,8 @@
/* Command tx and rx */
struct drm_gem_object *tx_cmd_buf;
u32 cmd_buffer_size;
+ u32 cmd_buffer_iova;
+ void *vaddr;
/* Debug Information */
struct dentry *debugfs_root;
@@ -377,14 +384,14 @@
int dsi_ctrl_host_deinit(struct dsi_ctrl *dsi_ctrl);
/**
- * dsi_ctrl_set_ulps() - set ULPS state for DSI lanes.
- * @dsi_ctrl: DSI controller handle.
- * @enable: enable/disable ULPS.
- *
- * ULPS can be enabled/disabled after DSI host engine is turned on.
- *
- * Return: error code.
- */
+ * dsi_ctrl_set_ulps() - set ULPS state for DSI lanes.
+ * @dsi_ctrl: DSI controller handle.
+ * @enable: enable/disable ULPS.
+ *
+ * ULPS can be enabled/disabled after DSI host engine is turned on.
+ *
+ * Return: error code.
+ */
int dsi_ctrl_set_ulps(struct dsi_ctrl *dsi_ctrl, bool enable);
/**
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index c2cf2cb..d6a7193 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -16,6 +16,7 @@
#include <linux/list.h>
#include <linux/of.h>
+#include <linux/err.h>
#include "msm_drv.h"
#include "dsi_display.h"
@@ -1004,9 +1005,9 @@
int i;
m_flags = (DSI_CTRL_CMD_BROADCAST | DSI_CTRL_CMD_BROADCAST_MASTER |
- DSI_CTRL_CMD_DEFER_TRIGGER | DSI_CTRL_CMD_FIFO_STORE);
+ DSI_CTRL_CMD_DEFER_TRIGGER | DSI_CTRL_CMD_FETCH_MEMORY);
flags = (DSI_CTRL_CMD_BROADCAST | DSI_CTRL_CMD_DEFER_TRIGGER |
- DSI_CTRL_CMD_FIFO_STORE);
+ DSI_CTRL_CMD_FETCH_MEMORY);
/*
* 1. Setup commands in FIFO
@@ -1101,8 +1102,8 @@
const struct mipi_dsi_msg *msg)
{
struct dsi_display *display = to_dsi_display(host);
-
- int rc = 0;
+ struct dsi_display_ctrl *display_ctrl;
+ int rc = 0, cnt = 0;
if (!host || !msg) {
pr_err("Invalid params\n");
@@ -1131,6 +1132,44 @@
goto error_disable_clks;
}
+ if (display->tx_cmd_buf == NULL) {
+ mutex_lock(&display->drm_dev->struct_mutex);
+ display->tx_cmd_buf = msm_gem_new(display->drm_dev,
+ SZ_4K,
+ MSM_BO_UNCACHED);
+ mutex_unlock(&display->drm_dev->struct_mutex);
+
+ display->cmd_buffer_size = SZ_4K;
+
+ if ((display->tx_cmd_buf) == NULL) {
+ pr_err("value of display->tx_cmd_buf is NULL");
+ goto error_disable_cmd_engine;
+ }
+ rc = msm_gem_get_iova(display->tx_cmd_buf, 0,
+ &(display->cmd_buffer_iova));
+ if (rc) {
+ pr_err("failed to get the iova rc %d\n", rc);
+ goto free_gem;
+ }
+
+ display->vaddr =
+ (void *) msm_gem_get_vaddr(display->tx_cmd_buf);
+
+ if (IS_ERR_OR_NULL(display->vaddr)) {
+ pr_err("failed to get va rc %d\n", rc);
+ rc = -EINVAL;
+ goto put_iova;
+ }
+
+ for (cnt = 0; cnt < display->ctrl_count; cnt++) {
+ display_ctrl = &display->ctrl[cnt];
+ display_ctrl->ctrl->cmd_buffer_size = SZ_4K;
+ display_ctrl->ctrl->cmd_buffer_iova =
+ display->cmd_buffer_iova;
+ display_ctrl->ctrl->vaddr = display->vaddr;
+ }
+ }
+
if (display->ctrl_count > 1 && !(msg->flags & MIPI_DSI_MSG_UNICAST)) {
rc = dsi_display_broadcast_cmd(display, msg);
if (rc) {
@@ -1143,13 +1182,19 @@
msg->ctrl : 0;
rc = dsi_ctrl_cmd_transfer(display->ctrl[ctrl_idx].ctrl, msg,
- DSI_CTRL_CMD_FIFO_STORE);
+ DSI_CTRL_CMD_FETCH_MEMORY);
if (rc) {
pr_err("[%s] cmd transfer failed, rc=%d\n",
display->name, rc);
goto error_disable_cmd_engine;
}
}
+ return rc;
+
+put_iova:
+ msm_gem_put_iova(display->tx_cmd_buf, 0);
+free_gem:
+ msm_gem_free_object(display->tx_cmd_buf);
error_disable_cmd_engine:
(void)dsi_display_cmd_engine_disable(display);
error_disable_clks:
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
index d2bc7d8..89f31af 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
@@ -155,6 +155,10 @@
bool ulps_enabled;
bool clamp_enabled;
bool phy_idle_power_off;
+ struct drm_gem_object *tx_cmd_buf;
+ u32 cmd_buffer_size;
+ u32 cmd_buffer_iova;
+ void *vaddr;
struct mipi_dsi_host host;
struct dsi_bridge *bridge;