[PATCH v5 07/10] drm/mediatek: add dsi transfer function

2016-08-02 Thread YT Shen
Hi CK,

On Tue, 2016-08-02 at 14:55 +0800, CK Hu wrote:
> Hi, YT:
> 
> On Thu, 2016-07-28 at 17:28 +0800, YT Shen wrote:
> > From: shaoming chen 
> > 
> > add dsi read/write commands for transfer function
> > 
> > Signed-off-by: shaoming chen 
> > ---
> >  drivers/gpu/drm/mediatek/mtk_dsi.c |  286 
> > 
> >  1 file changed, 286 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c 
> > b/drivers/gpu/drm/mediatek/mtk_dsi.c
> > index 553443a..1d36524 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> > @@ -24,6 +24,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  
> >  #include "mtk_drm_ddp_comp.h"
> > @@ -81,8 +82,16 @@
> >  #define DSI_HBP_WC 0x54
> >  #define DSI_HFP_WC 0x58
> >  
> > +#define DSI_CMDQ_SIZE  0x60
> > +#define CMDQ_SIZE  0x3f
> > +
> >  #define DSI_HSTX_CKL_WC0x64
> >  
> > +#define DSI_RX_DATA0   0x74
> > +#define DSI_RX_DATA1   0x78
> > +#define DSI_RX_DATA2   0x7c
> > +#define DSI_RX_DATA3   0x80
> > +
> >  #define DSI_RACK   0x84
> >  #define RACK   BIT(0)
> >  
> > @@ -118,8 +127,25 @@
> >  #define CLK_HS_POST(0xff << 8)
> >  #define CLK_HS_EXIT(0xff << 16)
> >  
> > +#define DSI_CMDQ0  0x180
> > +
> >  #define NS_TO_CYCLE(n, c)((n) / (c) + (((n) % (c)) ? 1 : 0))
> >  
> > +#define MTK_DSI_HOST_IS_READ(type) \
> > +   ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \
> > +   (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \
> > +   (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
> > +   (type == MIPI_DSI_DCS_READ))
> > +
> > +#define MTK_DSI_HOST_IS_WRITE(type) \
> > +   ((type == MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM) || \
> > +   (type == MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM) || \
> > +   (type == MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM) || \
> > +   (type == MIPI_DSI_DCS_SHORT_WRITE) || \
> > +   (type == MIPI_DSI_DCS_SHORT_WRITE_PARAM) || \
> > +   (type == MIPI_DSI_GENERIC_LONG_WRITE) || \
> > +   (type == MIPI_DSI_DCS_LONG_WRITE))
> > +
> >  struct phy;
> >  
> >  struct mtk_dsi {
> > @@ -149,6 +175,17 @@ struct mtk_dsi {
> > int irq_data;
> >  };
> >  
> > +struct dsi_rxtx_data {
> > +   u8 byte0;
> > +   u8 byte1;
> > +   u8 byte2;
> > +   u8 byte3;
> > +};
> > +
> > +struct dsi_tx_cmdq_regs {
> > +   struct dsi_rxtx_data data[128];
> > +};
> > +
> >  static wait_queue_head_t _dsi_cmd_done_wait_queue;
> >  static wait_queue_head_t _dsi_dcs_read_wait_queue;
> >  static wait_queue_head_t _dsi_wait_vm_done_queue;
> > @@ -813,9 +850,258 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host 
> > *host,
> > return 0;
> >  }
> >  
> > +static void mtk_dsi_set_cmdq(void __iomem *reg, u32 mask, u32 data)
> > +{
> > +   u32 temp = readl(reg);
> > +
> > +   writel((temp & ~mask) | (data & mask), reg);
> > +}
> > +
> > +static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
> > +{
> > +   u32 timeout_ms = 50; /* total 1s ~ 2s timeout */
> > +
> > +   while (timeout_ms--) {
> > +   if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY))
> > +   break;
> > +
> > +   usleep_range(2, 4);
> > +   }
> > +
> > +   if (timeout_ms == 0) {
> > +   dev_info(dsi->dev, "polling dsi wait not busy timeout!\n");
> > +
> > +   mtk_dsi_enable(dsi);
> > +   mtk_dsi_reset_engine(dsi);
> > +   }
> > +}
> > +
> > +static void mtk_dsi_wait_for_cmd_done(struct mtk_dsi *dsi)
> > +{
> > +   s32 ret = 0;
> > +   unsigned long timeout = msecs_to_jiffies(500);
> > +
> > +   ret = wait_event_interruptible_timeout(_dsi_cmd_done_wait_queue,
> > +   dsi->irq_data & CMD_DONE_INT_FLAG, timeout);
> > +   if (ret == 0) {
> > +   dev_info(dsi->dev, "dsi wait engine cmd done fail\n");
> > +   mtk_dsi_enable(dsi);
> > +   mtk_dsi_reset_engine(dsi);
> > +   return;
> > +   }
> > +
> > +   dsi->irq_data &= ~CMD_DONE_INT_FLAG;
> 
> I think you should move this before trigger HW. Sometimes this interrupt
> is coming and this flag is set but you do not wait this event and do not
> clear it. Then when you want to wait, the flag is already set by long
> time ago interrupt.
OK, we will fix it.

> 
> > +}
> > +
> > +static ssize_t mtk_dsi_host_read_cmd(struct mtk_dsi *dsi,
> > +const struct mipi_dsi_msg *msg)
> > +{
> > +   u8 max_try_count = 5;
> > +   u32 recv_cnt, tmp_val;
> > +   struct dsi_rxtx_data read_data0, read_data1, read_data2, read_data3;
> > +   u8 config, type, data0, data1;
> > +   s32 ret;
> > +
> > +   u8 *buffer = msg->rx_buf;
> > +   u8 buffer_size = msg->rx_len;
> > +
> > +   if (readl(dsi->regs + DSI_MODE_CTRL) & 0x03) {
> > +   dev_info(dsi->dev, "dsi engine is not command mode\n");
> > +   return -1;
> > +   }
> > +
> > +   if 

[PATCH v5 07/10] drm/mediatek: add dsi transfer function

2016-08-02 Thread CK Hu
Hi, YT:

On Thu, 2016-07-28 at 17:28 +0800, YT Shen wrote:
> From: shaoming chen 
> 
> add dsi read/write commands for transfer function
> 
> Signed-off-by: shaoming chen 
> ---
>  drivers/gpu/drm/mediatek/mtk_dsi.c |  286 
> 
>  1 file changed, 286 insertions(+)
> 
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c 
> b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 553443a..1d36524 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -24,6 +24,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  
>  #include "mtk_drm_ddp_comp.h"
> @@ -81,8 +82,16 @@
>  #define DSI_HBP_WC   0x54
>  #define DSI_HFP_WC   0x58
>  
> +#define DSI_CMDQ_SIZE0x60
> +#define CMDQ_SIZE0x3f
> +
>  #define DSI_HSTX_CKL_WC  0x64
>  
> +#define DSI_RX_DATA0 0x74
> +#define DSI_RX_DATA1 0x78
> +#define DSI_RX_DATA2 0x7c
> +#define DSI_RX_DATA3 0x80
> +
>  #define DSI_RACK 0x84
>  #define RACK BIT(0)
>  
> @@ -118,8 +127,25 @@
>  #define CLK_HS_POST  (0xff << 8)
>  #define CLK_HS_EXIT  (0xff << 16)
>  
> +#define DSI_CMDQ00x180
> +
>  #define NS_TO_CYCLE(n, c)((n) / (c) + (((n) % (c)) ? 1 : 0))
>  
> +#define MTK_DSI_HOST_IS_READ(type) \
> + ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \
> + (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \
> + (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
> + (type == MIPI_DSI_DCS_READ))
> +
> +#define MTK_DSI_HOST_IS_WRITE(type) \
> + ((type == MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM) || \
> + (type == MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM) || \
> + (type == MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM) || \
> + (type == MIPI_DSI_DCS_SHORT_WRITE) || \
> + (type == MIPI_DSI_DCS_SHORT_WRITE_PARAM) || \
> + (type == MIPI_DSI_GENERIC_LONG_WRITE) || \
> + (type == MIPI_DSI_DCS_LONG_WRITE))
> +
>  struct phy;
>  
>  struct mtk_dsi {
> @@ -149,6 +175,17 @@ struct mtk_dsi {
>   int irq_data;
>  };
>  
> +struct dsi_rxtx_data {
> + u8 byte0;
> + u8 byte1;
> + u8 byte2;
> + u8 byte3;
> +};
> +
> +struct dsi_tx_cmdq_regs {
> + struct dsi_rxtx_data data[128];
> +};
> +
>  static wait_queue_head_t _dsi_cmd_done_wait_queue;
>  static wait_queue_head_t _dsi_dcs_read_wait_queue;
>  static wait_queue_head_t _dsi_wait_vm_done_queue;
> @@ -813,9 +850,258 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host 
> *host,
>   return 0;
>  }
>  
> +static void mtk_dsi_set_cmdq(void __iomem *reg, u32 mask, u32 data)
> +{
> + u32 temp = readl(reg);
> +
> + writel((temp & ~mask) | (data & mask), reg);
> +}
> +
> +static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
> +{
> + u32 timeout_ms = 50; /* total 1s ~ 2s timeout */
> +
> + while (timeout_ms--) {
> + if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY))
> + break;
> +
> + usleep_range(2, 4);
> + }
> +
> + if (timeout_ms == 0) {
> + dev_info(dsi->dev, "polling dsi wait not busy timeout!\n");
> +
> + mtk_dsi_enable(dsi);
> + mtk_dsi_reset_engine(dsi);
> + }
> +}
> +
> +static void mtk_dsi_wait_for_cmd_done(struct mtk_dsi *dsi)
> +{
> + s32 ret = 0;
> + unsigned long timeout = msecs_to_jiffies(500);
> +
> + ret = wait_event_interruptible_timeout(_dsi_cmd_done_wait_queue,
> + dsi->irq_data & CMD_DONE_INT_FLAG, timeout);
> + if (ret == 0) {
> + dev_info(dsi->dev, "dsi wait engine cmd done fail\n");
> + mtk_dsi_enable(dsi);
> + mtk_dsi_reset_engine(dsi);
> + return;
> + }
> +
> + dsi->irq_data &= ~CMD_DONE_INT_FLAG;

I think you should move this before trigger HW. Sometimes this interrupt
is coming and this flag is set but you do not wait this event and do not
clear it. Then when you want to wait, the flag is already set by long
time ago interrupt.

> +}
> +
> +static ssize_t mtk_dsi_host_read_cmd(struct mtk_dsi *dsi,
> +  const struct mipi_dsi_msg *msg)
> +{
> + u8 max_try_count = 5;
> + u32 recv_cnt, tmp_val;
> + struct dsi_rxtx_data read_data0, read_data1, read_data2, read_data3;
> + u8 config, type, data0, data1;
> + s32 ret;
> +
> + u8 *buffer = msg->rx_buf;
> + u8 buffer_size = msg->rx_len;
> +
> + if (readl(dsi->regs + DSI_MODE_CTRL) & 0x03) {
> + dev_info(dsi->dev, "dsi engine is not command mode\n");
> + return -1;
> + }
> +
> + if (!buffer) {
> + dev_info(dsi->dev, "dsi receive buffer size may be NULL\n");
> + return -1;
> + }
> +
> + do {
> + if (max_try_count == 0) {
> + dev_info(dsi->dev, "dsi engine read counter has been 
> maxinum\n");
> + return -1;

[PATCH v5 07/10] drm/mediatek: add dsi transfer function

2016-07-28 Thread YT Shen
From: shaoming chen 

add dsi read/write commands for transfer function

Signed-off-by: shaoming chen 
---
 drivers/gpu/drm/mediatek/mtk_dsi.c |  286 
 1 file changed, 286 insertions(+)

diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c 
b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 553443a..1d36524 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 

 #include "mtk_drm_ddp_comp.h"
@@ -81,8 +82,16 @@
 #define DSI_HBP_WC 0x54
 #define DSI_HFP_WC 0x58

+#define DSI_CMDQ_SIZE  0x60
+#define CMDQ_SIZE  0x3f
+
 #define DSI_HSTX_CKL_WC0x64

+#define DSI_RX_DATA0   0x74
+#define DSI_RX_DATA1   0x78
+#define DSI_RX_DATA2   0x7c
+#define DSI_RX_DATA3   0x80
+
 #define DSI_RACK   0x84
 #define RACK   BIT(0)

@@ -118,8 +127,25 @@
 #define CLK_HS_POST(0xff << 8)
 #define CLK_HS_EXIT(0xff << 16)

+#define DSI_CMDQ0  0x180
+
 #define NS_TO_CYCLE(n, c)((n) / (c) + (((n) % (c)) ? 1 : 0))

+#define MTK_DSI_HOST_IS_READ(type) \
+   ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \
+   (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \
+   (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
+   (type == MIPI_DSI_DCS_READ))
+
+#define MTK_DSI_HOST_IS_WRITE(type) \
+   ((type == MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM) || \
+   (type == MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM) || \
+   (type == MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM) || \
+   (type == MIPI_DSI_DCS_SHORT_WRITE) || \
+   (type == MIPI_DSI_DCS_SHORT_WRITE_PARAM) || \
+   (type == MIPI_DSI_GENERIC_LONG_WRITE) || \
+   (type == MIPI_DSI_DCS_LONG_WRITE))
+
 struct phy;

 struct mtk_dsi {
@@ -149,6 +175,17 @@ struct mtk_dsi {
int irq_data;
 };

+struct dsi_rxtx_data {
+   u8 byte0;
+   u8 byte1;
+   u8 byte2;
+   u8 byte3;
+};
+
+struct dsi_tx_cmdq_regs {
+   struct dsi_rxtx_data data[128];
+};
+
 static wait_queue_head_t _dsi_cmd_done_wait_queue;
 static wait_queue_head_t _dsi_dcs_read_wait_queue;
 static wait_queue_head_t _dsi_wait_vm_done_queue;
@@ -813,9 +850,258 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
return 0;
 }

+static void mtk_dsi_set_cmdq(void __iomem *reg, u32 mask, u32 data)
+{
+   u32 temp = readl(reg);
+
+   writel((temp & ~mask) | (data & mask), reg);
+}
+
+static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
+{
+   u32 timeout_ms = 50; /* total 1s ~ 2s timeout */
+
+   while (timeout_ms--) {
+   if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY))
+   break;
+
+   usleep_range(2, 4);
+   }
+
+   if (timeout_ms == 0) {
+   dev_info(dsi->dev, "polling dsi wait not busy timeout!\n");
+
+   mtk_dsi_enable(dsi);
+   mtk_dsi_reset_engine(dsi);
+   }
+}
+
+static void mtk_dsi_wait_for_cmd_done(struct mtk_dsi *dsi)
+{
+   s32 ret = 0;
+   unsigned long timeout = msecs_to_jiffies(500);
+
+   ret = wait_event_interruptible_timeout(_dsi_cmd_done_wait_queue,
+   dsi->irq_data & CMD_DONE_INT_FLAG, timeout);
+   if (ret == 0) {
+   dev_info(dsi->dev, "dsi wait engine cmd done fail\n");
+   mtk_dsi_enable(dsi);
+   mtk_dsi_reset_engine(dsi);
+   return;
+   }
+
+   dsi->irq_data &= ~CMD_DONE_INT_FLAG;
+}
+
+static ssize_t mtk_dsi_host_read_cmd(struct mtk_dsi *dsi,
+const struct mipi_dsi_msg *msg)
+{
+   u8 max_try_count = 5;
+   u32 recv_cnt, tmp_val;
+   struct dsi_rxtx_data read_data0, read_data1, read_data2, read_data3;
+   u8 config, type, data0, data1;
+   s32 ret;
+
+   u8 *buffer = msg->rx_buf;
+   u8 buffer_size = msg->rx_len;
+
+   if (readl(dsi->regs + DSI_MODE_CTRL) & 0x03) {
+   dev_info(dsi->dev, "dsi engine is not command mode\n");
+   return -1;
+   }
+
+   if (!buffer) {
+   dev_info(dsi->dev, "dsi receive buffer size may be NULL\n");
+   return -1;
+   }
+
+   do {
+   if (max_try_count == 0) {
+   dev_info(dsi->dev, "dsi engine read counter has been 
maxinum\n");
+   return -1;
+   }
+
+   max_try_count--;
+   recv_cnt = 0;
+
+   mtk_dsi_wait_for_idle(dsi);
+
+   config = 0x04;
+   data0 = *((u8 *)(msg->tx_buf));
+
+   if (buffer_size < 3)
+   type = MIPI_DSI_DCS_READ;
+   else
+   type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
+
+   data1 = 0;
+
+   tmp_val = (data1