aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshaoming chen <shaoming.chen@mediatek.com>2017-03-31 07:30:36 -0400
committerCK Hu <ck.hu@mediatek.com>2017-04-07 12:02:15 -0400
commit21898816831fc60c92dd634ab4316a24da7eb4af (patch)
tree748180fff7b04bd5b19b9d2cdec860a0dd68ee13
parentdd5080a54df8261a18ed4e6587a2ec4a7b52a2e7 (diff)
drm/mediatek: add dsi transfer function
add dsi read/write commands for transfer function Signed-off-by: shaoming chen <shaoming.chen@mediatek.com> Acked-by: CK Hu <ck.hu@mediatek.com>
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dsi.c168
1 files changed, 166 insertions, 2 deletions
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 579556369555..2e2cc3a15cb6 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -24,6 +24,7 @@
24#include <linux/of_graph.h> 24#include <linux/of_graph.h>
25#include <linux/phy/phy.h> 25#include <linux/phy/phy.h>
26#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <video/mipi_display.h>
27#include <video/videomode.h> 28#include <video/videomode.h>
28 29
29#include "mtk_drm_ddp_comp.h" 30#include "mtk_drm_ddp_comp.h"
@@ -80,8 +81,16 @@
80#define DSI_HBP_WC 0x54 81#define DSI_HBP_WC 0x54
81#define DSI_HFP_WC 0x58 82#define DSI_HFP_WC 0x58
82 83
84#define DSI_CMDQ_SIZE 0x60
85#define CMDQ_SIZE 0x3f
86
83#define DSI_HSTX_CKL_WC 0x64 87#define DSI_HSTX_CKL_WC 0x64
84 88
89#define DSI_RX_DATA0 0x74
90#define DSI_RX_DATA1 0x78
91#define DSI_RX_DATA2 0x7c
92#define DSI_RX_DATA3 0x80
93
85#define DSI_RACK 0x84 94#define DSI_RACK 0x84
86#define RACK BIT(0) 95#define RACK BIT(0)
87 96
@@ -117,6 +126,15 @@
117#define CLK_HS_POST (0xff << 8) 126#define CLK_HS_POST (0xff << 8)
118#define CLK_HS_EXIT (0xff << 16) 127#define CLK_HS_EXIT (0xff << 16)
119 128
129#define DSI_CMDQ0 0x180
130#define CONFIG (0xff << 0)
131#define SHORT_PACKET 0
132#define LONG_PACKET 2
133#define BTA BIT(2)
134#define DATA_ID (0xff << 8)
135#define DATA_0 (0xff << 16)
136#define DATA_1 (0xff << 24)
137
120#define T_LPX 5 138#define T_LPX 5
121#define T_HS_PREP 6 139#define T_HS_PREP 6
122#define T_HS_TRAIL 8 140#define T_HS_TRAIL 8
@@ -125,6 +143,12 @@
125 143
126#define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0)) 144#define NS_TO_CYCLE(n, c) ((n) / (c) + (((n) % (c)) ? 1 : 0))
127 145
146#define MTK_DSI_HOST_IS_READ(type) \
147 ((type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) || \
148 (type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) || \
149 (type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM) || \
150 (type == MIPI_DSI_DCS_READ))
151
128struct phy; 152struct phy;
129 153
130struct mtk_dsi { 154struct mtk_dsi {
@@ -497,12 +521,12 @@ static void mtk_dsi_irq_data_set(struct mtk_dsi *dsi, u32 irq_bit)
497 dsi->irq_data |= irq_bit; 521 dsi->irq_data |= irq_bit;
498} 522}
499 523
500static __maybe_unused void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit) 524static void mtk_dsi_irq_data_clear(struct mtk_dsi *dsi, u32 irq_bit)
501{ 525{
502 dsi->irq_data &= ~irq_bit; 526 dsi->irq_data &= ~irq_bit;
503} 527}
504 528
505static __maybe_unused s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag, 529static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
506 unsigned int timeout) 530 unsigned int timeout)
507{ 531{
508 s32 ret = 0; 532 s32 ret = 0;
@@ -814,9 +838,149 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
814 return 0; 838 return 0;
815} 839}
816 840
841static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
842{
843 u32 timeout_ms = 500000; /* total 1s ~ 2s timeout */
844
845 while (timeout_ms--) {
846 if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY))
847 break;
848
849 usleep_range(2, 4);
850 }
851
852 if (timeout_ms == 0) {
853 DRM_WARN("polling dsi wait not busy timeout!\n");
854
855 mtk_dsi_enable(dsi);
856 mtk_dsi_reset_engine(dsi);
857 }
858}
859
860static u32 mtk_dsi_recv_cnt(u8 type, u8 *read_data)
861{
862 switch (type) {
863 case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
864 case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
865 return 1;
866 case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
867 case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
868 return 2;
869 case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
870 case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
871 return read_data[1] + read_data[2] * 16;
872 case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
873 DRM_INFO("type is 0x02, try again\n");
874 break;
875 default:
876 DRM_INFO("type(0x%x) cannot be non-recognite\n", type);
877 break;
878 }
879
880 return 0;
881}
882
883static void mtk_dsi_cmdq(struct mtk_dsi *dsi, const struct mipi_dsi_msg *msg)
884{
885 const char *tx_buf = msg->tx_buf;
886 u8 config, cmdq_size, cmdq_off, type = msg->type;
887 u32 reg_val, cmdq_mask, i;
888
889 if (MTK_DSI_HOST_IS_READ(type))
890 config = BTA;
891 else
892 config = (msg->tx_len > 2) ? LONG_PACKET : SHORT_PACKET;
893
894 if (msg->tx_len > 2) {
895 cmdq_size = 1 + (msg->tx_len + 3) / 4;
896 cmdq_off = 4;
897 cmdq_mask = CONFIG | DATA_ID | DATA_0 | DATA_1;
898 reg_val = (msg->tx_len << 16) | (type << 8) | config;
899 } else {
900 cmdq_size = 1;
901 cmdq_off = 2;
902 cmdq_mask = CONFIG | DATA_ID;
903 reg_val = (type << 8) | config;
904 }
905
906 for (i = 0; i < msg->tx_len; i++)
907 writeb(tx_buf[i], dsi->regs + DSI_CMDQ0 + cmdq_off + i);
908
909 mtk_dsi_mask(dsi, DSI_CMDQ0, cmdq_mask, reg_val);
910 mtk_dsi_mask(dsi, DSI_CMDQ_SIZE, CMDQ_SIZE, cmdq_size);
911}
912
913static ssize_t mtk_dsi_host_send_cmd(struct mtk_dsi *dsi,
914 const struct mipi_dsi_msg *msg, u8 flag)
915{
916 mtk_dsi_wait_for_idle(dsi);
917 mtk_dsi_irq_data_clear(dsi, flag);
918 mtk_dsi_cmdq(dsi, msg);
919 mtk_dsi_start(dsi);
920
921 if (!mtk_dsi_wait_for_irq_done(dsi, flag, 2000))
922 return -ETIME;
923 else
924 return 0;
925}
926
927static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
928 const struct mipi_dsi_msg *msg)
929{
930 struct mtk_dsi *dsi = host_to_dsi(host);
931 u32 recv_cnt, i;
932 u8 read_data[16];
933 void *src_addr;
934 u8 irq_flag = CMD_DONE_INT_FLAG;
935
936 if (readl(dsi->regs + DSI_MODE_CTRL) & MODE) {
937 DRM_ERROR("dsi engine is not command mode\n");
938 return -EINVAL;
939 }
940
941 if (MTK_DSI_HOST_IS_READ(msg->type))
942 irq_flag |= LPRX_RD_RDY_INT_FLAG;
943
944 if (mtk_dsi_host_send_cmd(dsi, msg, irq_flag) < 0)
945 return -ETIME;
946
947 if (!MTK_DSI_HOST_IS_READ(msg->type))
948 return 0;
949
950 if (!msg->rx_buf) {
951 DRM_ERROR("dsi receive buffer size may be NULL\n");
952 return -EINVAL;
953 }
954
955 for (i = 0; i < 16; i++)
956 *(read_data + i) = readb(dsi->regs + DSI_RX_DATA0 + i);
957
958 recv_cnt = mtk_dsi_recv_cnt(read_data[0], read_data);
959
960 if (recv_cnt > 2)
961 src_addr = &read_data[4];
962 else
963 src_addr = &read_data[1];
964
965 if (recv_cnt > 10)
966 recv_cnt = 10;
967
968 if (recv_cnt > msg->rx_len)
969 recv_cnt = msg->rx_len;
970
971 if (recv_cnt)
972 memcpy(msg->rx_buf, src_addr, recv_cnt);
973
974 DRM_INFO("dsi get %d byte data from the panel address(0x%x)\n",
975 recv_cnt, *((u8 *)(msg->tx_buf)));
976
977 return recv_cnt;
978}
979
817static const struct mipi_dsi_host_ops mtk_dsi_ops = { 980static const struct mipi_dsi_host_ops mtk_dsi_ops = {
818 .attach = mtk_dsi_host_attach, 981 .attach = mtk_dsi_host_attach,
819 .detach = mtk_dsi_host_detach, 982 .detach = mtk_dsi_host_detach,
983 .transfer = mtk_dsi_host_transfer,
820}; 984};
821 985
822static int mtk_dsi_bind(struct device *dev, struct device *master, void *data) 986static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)