diff options
author | Shohei Sakamoto <sakamotos@casio.co.jp> | 2016-01-25 20:47:58 +0900 |
---|---|---|
committer | Shohei Sakamoto <sakamotos@casio.co.jp> | 2016-01-25 20:47:58 +0900 |
commit | eea727f511dbdc913e0e6f16d84e1e5074049ef3 (patch) | |
tree | d1d861c0957ba5164d080cd1ac916e515984a3f8 | |
parent | 88ef1b0e5cbdafde4eda0b37228e6f7bc2bb5e18 (diff) | |
download | koi-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.h | 5 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-exynos/mipi_dsim.h | 14 | ||||
-rw-r--r-- | drivers/video/exynos_mipi_dsi.c | 1 | ||||
-rw-r--r-- | drivers/video/exynos_mipi_dsi_common.c | 122 | ||||
-rw-r--r-- | drivers/video/exynos_mipi_dsi_common.h | 5 | ||||
-rw-r--r-- | drivers/video/exynos_mipi_dsi_lowlevel.c | 18 | ||||
-rw-r--r-- | drivers/video/exynos_mipi_dsi_lowlevel.h | 3 |
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); |