summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShohei Sakamoto <sakamotos@casio.co.jp>2016-01-25 20:47:58 +0900
committerShohei Sakamoto <sakamotos@casio.co.jp>2016-01-25 20:47:58 +0900
commiteea727f511dbdc913e0e6f16d84e1e5074049ef3 (patch)
treed1d861c0957ba5164d080cd1ac916e515984a3f8
parent88ef1b0e5cbdafde4eda0b37228e6f7bc2bb5e18 (diff)
downloadkoi-uboot-eea727f511dbdc913e0e6f16d84e1e5074049ef3.tar.gz
mipi : add read command
Change-Id: Ic3b8a3252444b3b19fe99af933171e227788f480 Signed-off-by: Itsuki Yamashita <yamashitai@casio.co.jp> Signed-off-by: Sanghee Kim <haya93@samsung.com>
-rw-r--r--arch/arm/include/asm/arch-exynos/dsim.h5
-rw-r--r--arch/arm/include/asm/arch-exynos/mipi_dsim.h14
-rw-r--r--drivers/video/exynos_mipi_dsi.c1
-rw-r--r--drivers/video/exynos_mipi_dsi_common.c122
-rw-r--r--drivers/video/exynos_mipi_dsi_common.h5
-rw-r--r--drivers/video/exynos_mipi_dsi_lowlevel.c18
-rw-r--r--drivers/video/exynos_mipi_dsi_lowlevel.h3
7 files changed, 162 insertions, 6 deletions
diff --git a/arch/arm/include/asm/arch-exynos/dsim.h b/arch/arm/include/asm/arch-exynos/dsim.h
index e148aca2e..50584f1b7 100644
--- a/arch/arm/include/asm/arch-exynos/dsim.h
+++ b/arch/arm/include/asm/arch-exynos/dsim.h
@@ -149,12 +149,17 @@ struct exynos_mipi_dsim {
#define INTSRC_FRAME_DONE (1 << 24)
#define INTSRC_PLL_STABLE (1 << 31)
#define INTSRC_SWRST_RELEASE (1 << 30)
+#define DSIM_INIT_RX (1 << 4) /* MD fifo read point initialize */
+
/* EXYNOS_DSIM_INTMSK */
#define INTMSK_FRAME_DONE (1 << 24)
+#define INTSRC_RX_DATA_DONE (1 << 18)
/* EXYNOS_DSIM_FIFOCTRL */
#define SFR_HEADER_EMPTY (1 << 22)
+#define DSIM_FIFOCTRL (0x44) /* FIFO status and control register */
+#define DSIM_EMPTY_RX (1 << 24) /* Rx fifo empty */
/* EXYNOS_DSIM_PKTHDR */
#define DSIM_PKTHDR_DI(x) (((x) & 0x3f) << 0)
diff --git a/arch/arm/include/asm/arch-exynos/mipi_dsim.h b/arch/arm/include/asm/arch-exynos/mipi_dsim.h
index 9a7cbeb59..d40801c05 100644
--- a/arch/arm/include/asm/arch-exynos/mipi_dsim.h
+++ b/arch/arm/include/asm/arch-exynos/mipi_dsim.h
@@ -120,6 +120,18 @@ enum {
MIPI_DSI_PACKED_PIXEL_STREAM_24 = 0x3e,
};
+/* MIPI DSI Peripheral-to-Processor transaction types */
+enum {
+ MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT = 0x02,
+ MIPI_DSI_RX_END_OF_TRANSMISSION = 0x08,
+ MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE = 0x11,
+ MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE = 0x12,
+ MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE = 0x1a,
+ MIPI_DSI_RX_DCS_LONG_READ_RESPONSE = 0x1c,
+ MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE = 0x21,
+ MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE = 0x22,
+};
+
/*
* struct mipi_dsim_config - interface for configuring mipi-dsi controller.
*
@@ -306,7 +318,7 @@ struct mipi_dsim_master_ops {
int (*cmd_write)(struct mipi_dsim_device *dsim, unsigned int data_id,
unsigned int data0, unsigned int data1);
int (*cmd_read)(struct mipi_dsim_device *dsim, unsigned int data_id,
- unsigned int data0, unsigned int data1);
+ unsigned int addr, unsigned int count, char *buf);
int (*get_dsim_frame_done)(struct mipi_dsim_device *dsim);
int (*clear_dsim_frame_done)(struct mipi_dsim_device *dsim);
diff --git a/drivers/video/exynos_mipi_dsi.c b/drivers/video/exynos_mipi_dsi.c
index 9f938013d..0188099c9 100644
--- a/drivers/video/exynos_mipi_dsi.c
+++ b/drivers/video/exynos_mipi_dsi.c
@@ -180,6 +180,7 @@ struct mipi_dsim_ddi
/* define MIPI-DSI Master operations. */
static struct mipi_dsim_master_ops master_ops = {
.cmd_write = exynos_mipi_dsi_wr_data,
+ .cmd_read = exynos_mipi_dsi_rd_data,
.get_dsim_frame_done = exynos_mipi_dsi_get_frame_done_status,
.clear_dsim_frame_done = exynos_mipi_dsi_clear_frame_done,
};
diff --git a/drivers/video/exynos_mipi_dsi_common.c b/drivers/video/exynos_mipi_dsi_common.c
index 6e5d9840c..6531470f0 100644
--- a/drivers/video/exynos_mipi_dsi_common.c
+++ b/drivers/video/exynos_mipi_dsi_common.c
@@ -27,6 +27,9 @@
#include <asm/arch/mipi_dsim.h>
#include "exynos_mipi_dsi_lowlevel.h"
+#include "exynos_mipi_dsi_common.h"
+
+#define DSIM_RX_FIFO_MAX_DEPTH 64
#define MHZ (1000 * 1000)
#define FIN_HZ (24 * MHZ)
@@ -248,6 +251,123 @@ int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
return 0;
}
+static void exynos_mipi_dsi_rx_err_handler(struct mipi_dsim_device *dsim,
+ unsigned int rx_fifo)
+{
+ /* Parse error report bit*/
+ if (rx_fifo & (1 << 8))
+ printf("SoT error!\n");
+ if (rx_fifo & (1 << 9))
+ printf("SoT sync error!\n");
+ if (rx_fifo & (1 << 10))
+ printf("EoT error!\n");
+ if (rx_fifo & (1 << 11))
+ printf("Escape mode entry command error!\n");
+ if (rx_fifo & (1 << 12))
+ printf("Low-power transmit sync error!\n");
+ if (rx_fifo & (1 << 13))
+ printf("HS receive timeout error!\n");
+ if (rx_fifo & (1 << 14))
+ printf("False control error!\n");
+ /* Bit 15 is reserved*/
+ if (rx_fifo & (1 << 16))
+ printf("ECC error, single-bit(detected and corrected)!\n");
+ if (rx_fifo & (1 << 17))
+ printf("ECC error, multi-bit(detected, not corrected)!\n");
+ if (rx_fifo & (1 << 18))
+ printf("Checksum error(long packet only)!\n");
+ if (rx_fifo & (1 << 19))
+ printf("DSI data type not recognized!\n");
+ if (rx_fifo & (1 << 20))
+ printf("DSI VC ID invalid!\n");
+ if (rx_fifo & (1 << 21))
+ printf("Invalid transmission length!\n");
+ /* Bit 22 is reserved */
+ if (rx_fifo & (1 << 23))
+ printf("DSI protocol violation!\n");
+}
+
+int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id,
+ unsigned int addr, unsigned int count, char *buf)
+{
+ struct exynos_mipi_dsim *mipi_dsim =
+ (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim();
+ unsigned int timeout = TRY_GET_FIFO_TIMEOUT;
+ unsigned int rx_fifo, rx_size = 0;
+ int i, j, ret = 0;
+ u32 rx_fifo_depth = DSIM_RX_FIFO_MAX_DEPTH;
+
+ /* Init RX FIFO before read and clear DSIM_INTSRC */
+ exynos_mipi_dsi_init_fifo_pointer(dsim, DSIM_INIT_RX);
+ exynos_mipi_dsi_clear_interrupt(dsim,INTSRC_RX_DATA_DONE);
+
+ /* Set the maximum packet size returned */
+ exynos_mipi_dsi_wr_data(dsim,
+ MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, count, 0);
+
+ /* Read request */
+ exynos_mipi_dsi_wr_data(dsim, data_id, addr, 0);
+
+ mdelay(200);
+
+ do {
+ rx_fifo = readl(&mipi_dsim->rxfifo);
+
+ /* Parse the RX packet data types */
+ switch (rx_fifo & 0xff) {
+ case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
+ exynos_mipi_dsi_rx_err_handler(dsim, rx_fifo);
+ if (ret < 0) {
+ goto exit;
+ }
+ break;
+ case MIPI_DSI_RX_END_OF_TRANSMISSION:
+ printf("EoTp was received from LCD module.\n");
+ break;
+ case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
+ case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
+ case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
+ case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
+ printf("Short Packet was received from LCD module.\n");
+ for (i = 0; i <= count; i++)
+ buf[i] = (rx_fifo >> (8 + i * 8)) & 0xff;
+ break;
+ case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
+ case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
+ printf("Long Packet was received from LCD module.\n");
+ rx_size = (rx_fifo & 0x00ffff00) >> 8;
+ printf("rx fifo : %8x, response : %x, rx_size : %d\n",
+ rx_fifo, rx_fifo & 0xff, rx_size);
+ /* Read data from RX packet payload */
+ for (i = 0; i < rx_size >> 2; i++) {
+ rx_fifo = readl(&mipi_dsim->rxfifo);
+ for (j = 0; j < 4; j++)
+ buf[(i*4)+j] = (u8)(rx_fifo >> (j * 8)) & 0xff;
+ }
+ if (rx_size % 4) {
+ rx_fifo = readl(&mipi_dsim->rxfifo);
+ for (j = 0; j < rx_size % 4; j++)
+ buf[4 * i + j] =
+ (u8)(rx_fifo >> (j * 8)) & 0xff;
+ }
+ break;
+ default:
+ printf("Packet format is invaild.\n");
+ ret = -EBUSY;
+ break;
+ }
+ } while (!exynos_mipi_dsi_rx_fifo_is_empty(dsim) && --rx_fifo_depth);
+
+ ret = rx_size;
+ if (!rx_fifo_depth) {
+ printf("Check DPHY values about HS clk.\n");
+ ret = -EBUSY;
+ }
+
+exit:
+ return ret;
+}
+
int exynos_mipi_dsi_pll_on(struct mipi_dsim_device *dsim, unsigned int enable)
{
int sw_timeout;
@@ -255,7 +375,7 @@ int exynos_mipi_dsi_pll_on(struct mipi_dsim_device *dsim, unsigned int enable)
if (enable) {
sw_timeout = 1000;
- exynos_mipi_dsi_clear_interrupt(dsim);
+ exynos_mipi_dsi_clear_interrupt(dsim, INTSRC_PLL_STABLE);
exynos_mipi_dsi_enable_pll(dsim, 1);
while (1) {
sw_timeout--;
diff --git a/drivers/video/exynos_mipi_dsi_common.h b/drivers/video/exynos_mipi_dsi_common.h
index 9fe7ab39f..a7887d579 100644
--- a/drivers/video/exynos_mipi_dsi_common.h
+++ b/drivers/video/exynos_mipi_dsi_common.h
@@ -25,8 +25,13 @@
#ifndef _EXYNOS_MIPI_DSI_COMMON_H
#define _EXYNOS_MIPI_DSI_COMMON_H
+#define DSIM_RX_FIFO_READ_DONE (0x30800002)
+#define DSIM_MAX_RX_FIFO (64)
+
int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
unsigned int data0, unsigned int data1);
+int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id,
+ unsigned int addr, unsigned int count, char *buf);
int exynos_mipi_dsi_pll_on(struct mipi_dsim_device *dsim, unsigned int enable);
unsigned long exynos_mipi_dsi_change_pll(struct mipi_dsim_device *dsim,
unsigned int pre_divider, unsigned int main_divider,
diff --git a/drivers/video/exynos_mipi_dsi_lowlevel.c b/drivers/video/exynos_mipi_dsi_lowlevel.c
index d61b77361..96591b4ab 100644
--- a/drivers/video/exynos_mipi_dsi_lowlevel.c
+++ b/drivers/video/exynos_mipi_dsi_lowlevel.c
@@ -574,15 +574,14 @@ void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep)
writel(reg, &mipi_dsim->pllctrl);
}
-void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim)
+void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim, unsigned int int_src)
{
struct exynos_mipi_dsim *mipi_dsim =
(struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim();
unsigned int reg = readl(&mipi_dsim->intsrc);
- reg |= INTSRC_PLL_STABLE;
+ writel(int_src, &mipi_dsim->intsrc);
- writel(reg, &mipi_dsim->intsrc);
}
void exynos_mipi_dsi_clear_all_interrupt(struct mipi_dsim_device *dsim)
@@ -612,6 +611,19 @@ unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim)
return readl(&mipi_dsim->fifoctrl) & ~(0x1f);
}
+unsigned int exynos_mipi_dsi_rx_fifo_is_empty(struct mipi_dsim_device *dsim)
+{
+ struct exynos_mipi_dsim *mipi_dsim =
+ (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim();
+
+ unsigned int reg;
+
+ reg = readl(&mipi_dsim->fifoctrl);
+
+ return (reg & DSIM_EMPTY_RX) ? 1 : 0;
+}
+
+
void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim,
unsigned int di, unsigned int data0, unsigned int data1)
{
diff --git a/drivers/video/exynos_mipi_dsi_lowlevel.h b/drivers/video/exynos_mipi_dsi_lowlevel.h
index 4b8c441cb..28b3ed2d5 100644
--- a/drivers/video/exynos_mipi_dsi_lowlevel.h
+++ b/drivers/video/exynos_mipi_dsi_lowlevel.h
@@ -96,7 +96,8 @@ void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim,
unsigned int hs_zero);
void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim,
unsigned int prep);
-void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim);
+void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim,
+ unsigned int int_src);
void exynos_mipi_dsi_clear_all_interrupt(struct mipi_dsim_device *dsim);
unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim);
unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim);