diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_dsi.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_dsi.c | 243 |
1 files changed, 125 insertions, 118 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index e977a81af2e6..63c84a106c0b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -10,6 +10,8 @@ * published by the Free Software Foundation. */ +#include <asm/unaligned.h> + #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_mipi_dsi.h> @@ -209,12 +211,6 @@ #define OLD_SCLK_MIPI_CLK_NAME "pll_clk" -#define REG_ADDR(dsi, reg_idx) ((dsi)->reg_base + \ - dsi->driver_data->reg_ofs[(reg_idx)]) -#define DSI_WRITE(dsi, reg_idx, val) writel((val), \ - REG_ADDR((dsi), (reg_idx))) -#define DSI_READ(dsi, reg_idx) readl(REG_ADDR((dsi), (reg_idx))) - static char *clk_names[5] = { "bus_clk", "sclk_mipi", "phyclk_mipidphy0_bitclkdiv8", "phyclk_mipidphy0_rxclkesc0", "sclk_rgb_vclk_to_dsim0" }; @@ -228,12 +224,8 @@ struct exynos_dsi_transfer { struct list_head list; struct completion completed; int result; - u8 data_id; - u8 data[2]; + struct mipi_dsi_packet packet; u16 flags; - - const u8 *tx_payload; - u16 tx_len; u16 tx_done; u8 *rx_payload; @@ -247,7 +239,7 @@ struct exynos_dsi_transfer { #define DSIM_STATE_VIDOUT_AVAILABLE BIT(3) struct exynos_dsi_driver_data { - unsigned int *reg_ofs; + const unsigned int *reg_ofs; unsigned int plltmr_reg; unsigned int has_freqband:1; unsigned int has_clklane_stop:1; @@ -255,7 +247,7 @@ struct exynos_dsi_driver_data { unsigned int max_freq; unsigned int wait_for_reset; unsigned int num_bits_resol; - unsigned int *reg_values; + const unsigned int *reg_values; }; struct exynos_dsi { @@ -324,7 +316,20 @@ enum reg_idx { DSIM_PHYTIMING2_REG, NUM_REGS }; -static unsigned int exynos_reg_ofs[] = { + +static inline void exynos_dsi_write(struct exynos_dsi *dsi, enum reg_idx idx, + u32 val) +{ + + writel(val, dsi->reg_base + dsi->driver_data->reg_ofs[idx]); +} + +static inline u32 exynos_dsi_read(struct exynos_dsi *dsi, enum reg_idx idx) +{ + return readl(dsi->reg_base + dsi->driver_data->reg_ofs[idx]); +} + +static const unsigned int exynos_reg_ofs[] = { [DSIM_STATUS_REG] = 0x00, [DSIM_SWRST_REG] = 0x04, [DSIM_CLKCTRL_REG] = 0x08, @@ -348,7 +353,7 @@ static unsigned int exynos_reg_ofs[] = { [DSIM_PHYTIMING2_REG] = 0x6c, }; -static unsigned int exynos5433_reg_ofs[] = { +static const unsigned int exynos5433_reg_ofs[] = { [DSIM_STATUS_REG] = 0x04, [DSIM_SWRST_REG] = 0x0C, [DSIM_CLKCTRL_REG] = 0x10, @@ -390,7 +395,7 @@ enum reg_value_idx { PHYTIMING_HS_TRAIL }; -static unsigned int reg_values[] = { +static const unsigned int reg_values[] = { [RESET_TYPE] = DSIM_SWRST, [PLL_TIMER] = 500, [STOP_STATE_CNT] = 0xf, @@ -408,7 +413,25 @@ static unsigned int reg_values[] = { [PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0b), }; -static unsigned int exynos5433_reg_values[] = { +static const unsigned int exynos5422_reg_values[] = { + [RESET_TYPE] = DSIM_SWRST, + [PLL_TIMER] = 500, + [STOP_STATE_CNT] = 0xf, + [PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0xaf), + [PHYCTRL_VREG_LP] = 0, + [PHYCTRL_SLEW_UP] = 0, + [PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x08), + [PHYTIMING_HS_EXIT] = DSIM_PHYTIMING_HS_EXIT(0x0d), + [PHYTIMING_CLK_PREPARE] = DSIM_PHYTIMING1_CLK_PREPARE(0x09), + [PHYTIMING_CLK_ZERO] = DSIM_PHYTIMING1_CLK_ZERO(0x30), + [PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0e), + [PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x0a), + [PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x0c), + [PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x11), + [PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0d), +}; + +static const unsigned int exynos5433_reg_values[] = { [RESET_TYPE] = DSIM_FUNCRST, [PLL_TIMER] = 22200, [STOP_STATE_CNT] = 0xa, @@ -426,7 +449,7 @@ static unsigned int exynos5433_reg_values[] = { [PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0c), }; -static struct exynos_dsi_driver_data exynos3_dsi_driver_data = { +static const struct exynos_dsi_driver_data exynos3_dsi_driver_data = { .reg_ofs = exynos_reg_ofs, .plltmr_reg = 0x50, .has_freqband = 1, @@ -438,7 +461,7 @@ static struct exynos_dsi_driver_data exynos3_dsi_driver_data = { .reg_values = reg_values, }; -static struct exynos_dsi_driver_data exynos4_dsi_driver_data = { +static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = { .reg_ofs = exynos_reg_ofs, .plltmr_reg = 0x50, .has_freqband = 1, @@ -450,7 +473,7 @@ static struct exynos_dsi_driver_data exynos4_dsi_driver_data = { .reg_values = reg_values, }; -static struct exynos_dsi_driver_data exynos4415_dsi_driver_data = { +static const struct exynos_dsi_driver_data exynos4415_dsi_driver_data = { .reg_ofs = exynos_reg_ofs, .plltmr_reg = 0x58, .has_clklane_stop = 1, @@ -461,7 +484,7 @@ static struct exynos_dsi_driver_data exynos4415_dsi_driver_data = { .reg_values = reg_values, }; -static struct exynos_dsi_driver_data exynos5_dsi_driver_data = { +static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = { .reg_ofs = exynos_reg_ofs, .plltmr_reg = 0x58, .num_clks = 2, @@ -471,7 +494,7 @@ static struct exynos_dsi_driver_data exynos5_dsi_driver_data = { .reg_values = reg_values, }; -static struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { +static const struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { .reg_ofs = exynos5433_reg_ofs, .plltmr_reg = 0xa0, .has_clklane_stop = 1, @@ -482,7 +505,18 @@ static struct exynos_dsi_driver_data exynos5433_dsi_driver_data = { .reg_values = exynos5433_reg_values, }; -static struct of_device_id exynos_dsi_of_match[] = { +static const struct exynos_dsi_driver_data exynos5422_dsi_driver_data = { + .reg_ofs = exynos5433_reg_ofs, + .plltmr_reg = 0xa0, + .has_clklane_stop = 1, + .num_clks = 2, + .max_freq = 1500, + .wait_for_reset = 1, + .num_bits_resol = 12, + .reg_values = exynos5422_reg_values, +}; + +static const struct of_device_id exynos_dsi_of_match[] = { { .compatible = "samsung,exynos3250-mipi-dsi", .data = &exynos3_dsi_driver_data }, { .compatible = "samsung,exynos4210-mipi-dsi", @@ -491,6 +525,8 @@ static struct of_device_id exynos_dsi_of_match[] = { .data = &exynos4415_dsi_driver_data }, { .compatible = "samsung,exynos5410-mipi-dsi", .data = &exynos5_dsi_driver_data }, + { .compatible = "samsung,exynos5422-mipi-dsi", + .data = &exynos5422_dsi_driver_data }, { .compatible = "samsung,exynos5433-mipi-dsi", .data = &exynos5433_dsi_driver_data }, { } @@ -515,10 +551,10 @@ static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi) static void exynos_dsi_reset(struct exynos_dsi *dsi) { - struct exynos_dsi_driver_data *driver_data = dsi->driver_data; + u32 reset_val = dsi->driver_data->reg_values[RESET_TYPE]; reinit_completion(&dsi->completed); - DSI_WRITE(dsi, DSIM_SWRST_REG, driver_data->reg_values[RESET_TYPE]); + exynos_dsi_write(dsi, DSIM_SWRST_REG, reset_val); } #ifndef MHZ @@ -621,7 +657,7 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi, reg |= DSIM_FREQ_BAND(band); } - DSI_WRITE(dsi, DSIM_PLLCTRL_REG, reg); + exynos_dsi_write(dsi, DSIM_PLLCTRL_REG, reg); timeout = 1000; do { @@ -629,7 +665,7 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi, dev_err(dsi->dev, "PLL failed to stabilize\n"); return 0; } - reg = DSI_READ(dsi, DSIM_STATUS_REG); + reg = exynos_dsi_read(dsi, DSIM_STATUS_REG); } while ((reg & DSIM_PLL_STABLE) == 0); return fout; @@ -659,7 +695,7 @@ static int exynos_dsi_enable_clock(struct exynos_dsi *dsi) dev_dbg(dsi->dev, "hs_clk = %lu, byte_clk = %lu, esc_clk = %lu\n", hs_clk, byte_clk, esc_clk); - reg = DSI_READ(dsi, DSIM_CLKCTRL_REG); + reg = exynos_dsi_read(dsi, DSIM_CLKCTRL_REG); reg &= ~(DSIM_ESC_PRESCALER_MASK | DSIM_LANE_ESC_CLK_EN_CLK | DSIM_LANE_ESC_CLK_EN_DATA_MASK | DSIM_PLL_BYPASS | DSIM_BYTE_CLK_SRC_MASK); @@ -669,7 +705,7 @@ static int exynos_dsi_enable_clock(struct exynos_dsi *dsi) | DSIM_LANE_ESC_CLK_EN_DATA(BIT(dsi->lanes) - 1) | DSIM_BYTE_CLK_SRC(0) | DSIM_TX_REQUEST_HSCLK; - DSI_WRITE(dsi, DSIM_CLKCTRL_REG, reg); + exynos_dsi_write(dsi, DSIM_CLKCTRL_REG, reg); return 0; } @@ -677,7 +713,7 @@ static int exynos_dsi_enable_clock(struct exynos_dsi *dsi) static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi) { struct exynos_dsi_driver_data *driver_data = dsi->driver_data; - unsigned int *reg_values = driver_data->reg_values; + const unsigned int *reg_values = driver_data->reg_values; u32 reg; if (driver_data->has_freqband) @@ -686,7 +722,7 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi) /* B D-PHY: D-PHY Master & Slave Analog Block control */ reg = reg_values[PHYCTRL_ULPS_EXIT] | reg_values[PHYCTRL_VREG_LP] | reg_values[PHYCTRL_SLEW_UP]; - DSI_WRITE(dsi, DSIM_PHYCTRL_REG, reg); + exynos_dsi_write(dsi, DSIM_PHYCTRL_REG, reg); /* * T LPX: Transmitted length of any Low-Power state period @@ -694,7 +730,7 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi) * burst */ reg = reg_values[PHYTIMING_LPX] | reg_values[PHYTIMING_HS_EXIT]; - DSI_WRITE(dsi, DSIM_PHYTIMING_REG, reg); + exynos_dsi_write(dsi, DSIM_PHYTIMING_REG, reg); /* * T CLK-PREPARE: Time that the transmitter drives the Clock Lane LP-00 @@ -714,7 +750,7 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi) reg_values[PHYTIMING_CLK_POST] | reg_values[PHYTIMING_CLK_TRAIL]; - DSI_WRITE(dsi, DSIM_PHYTIMING1_REG, reg); + exynos_dsi_write(dsi, DSIM_PHYTIMING1_REG, reg); /* * T HS-PREPARE: Time that the transmitter drives the Data Lane LP-00 @@ -727,29 +763,29 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi) */ reg = reg_values[PHYTIMING_HS_PREPARE] | reg_values[PHYTIMING_HS_ZERO] | reg_values[PHYTIMING_HS_TRAIL]; - DSI_WRITE(dsi, DSIM_PHYTIMING2_REG, reg); + exynos_dsi_write(dsi, DSIM_PHYTIMING2_REG, reg); } static void exynos_dsi_disable_clock(struct exynos_dsi *dsi) { u32 reg; - reg = DSI_READ(dsi, DSIM_CLKCTRL_REG); + reg = exynos_dsi_read(dsi, DSIM_CLKCTRL_REG); reg &= ~(DSIM_LANE_ESC_CLK_EN_CLK | DSIM_LANE_ESC_CLK_EN_DATA_MASK | DSIM_ESC_CLKEN | DSIM_BYTE_CLKEN); - DSI_WRITE(dsi, DSIM_CLKCTRL_REG, reg); + exynos_dsi_write(dsi, DSIM_CLKCTRL_REG, reg); - reg = DSI_READ(dsi, DSIM_PLLCTRL_REG); + reg = exynos_dsi_read(dsi, DSIM_PLLCTRL_REG); reg &= ~DSIM_PLL_EN; - DSI_WRITE(dsi, DSIM_PLLCTRL_REG, reg); + exynos_dsi_write(dsi, DSIM_PLLCTRL_REG, reg); } static void exynos_dsi_enable_lane(struct exynos_dsi *dsi, u32 lane) { - u32 reg = DSI_READ(dsi, DSIM_CONFIG_REG); + u32 reg = exynos_dsi_read(dsi, DSIM_CONFIG_REG); reg |= (DSIM_NUM_OF_DATA_LANE(dsi->lanes - 1) | DSIM_LANE_EN_CLK | DSIM_LANE_EN(lane)); - DSI_WRITE(dsi, DSIM_CONFIG_REG, reg); + exynos_dsi_write(dsi, DSIM_CONFIG_REG, reg); } static int exynos_dsi_init_link(struct exynos_dsi *dsi) @@ -760,14 +796,14 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi) u32 lanes_mask; /* Initialize FIFO pointers */ - reg = DSI_READ(dsi, DSIM_FIFOCTRL_REG); + reg = exynos_dsi_read(dsi, DSIM_FIFOCTRL_REG); reg &= ~0x1f; - DSI_WRITE(dsi, DSIM_FIFOCTRL_REG, reg); + exynos_dsi_write(dsi, DSIM_FIFOCTRL_REG, reg); usleep_range(9000, 11000); reg |= 0x1f; - DSI_WRITE(dsi, DSIM_FIFOCTRL_REG, reg); + exynos_dsi_write(dsi, DSIM_FIFOCTRL_REG, reg); usleep_range(9000, 11000); /* DSI configuration */ @@ -836,7 +872,7 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi) dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) { reg |= DSIM_CLKLANE_STOP; } - DSI_WRITE(dsi, DSIM_CONFIG_REG, reg); + exynos_dsi_write(dsi, DSIM_CONFIG_REG, reg); lanes_mask = BIT(dsi->lanes) - 1; exynos_dsi_enable_lane(dsi, lanes_mask); @@ -849,19 +885,19 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi) return -EFAULT; } - reg = DSI_READ(dsi, DSIM_STATUS_REG); + reg = exynos_dsi_read(dsi, DSIM_STATUS_REG); if ((reg & DSIM_STOP_STATE_DAT(lanes_mask)) != DSIM_STOP_STATE_DAT(lanes_mask)) continue; } while (!(reg & (DSIM_STOP_STATE_CLK | DSIM_TX_READY_HS_CLK))); - reg = DSI_READ(dsi, DSIM_ESCMODE_REG); + reg = exynos_dsi_read(dsi, DSIM_ESCMODE_REG); reg &= ~DSIM_STOP_STATE_CNT_MASK; reg |= DSIM_STOP_STATE_CNT(driver_data->reg_values[STOP_STATE_CNT]); - DSI_WRITE(dsi, DSIM_ESCMODE_REG, reg); + exynos_dsi_write(dsi, DSIM_ESCMODE_REG, reg); reg = DSIM_BTA_TIMEOUT(0xff) | DSIM_LPDR_TIMEOUT(0xffff); - DSI_WRITE(dsi, DSIM_TIMEOUT_REG, reg); + exynos_dsi_write(dsi, DSIM_TIMEOUT_REG, reg); return 0; } @@ -876,20 +912,20 @@ static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi) reg = DSIM_CMD_ALLOW(0xf) | DSIM_STABLE_VFP(vm->vfront_porch) | DSIM_MAIN_VBP(vm->vback_porch); - DSI_WRITE(dsi, DSIM_MVPORCH_REG, reg); + exynos_dsi_write(dsi, DSIM_MVPORCH_REG, reg); reg = DSIM_MAIN_HFP(vm->hfront_porch) | DSIM_MAIN_HBP(vm->hback_porch); - DSI_WRITE(dsi, DSIM_MHPORCH_REG, reg); + exynos_dsi_write(dsi, DSIM_MHPORCH_REG, reg); reg = DSIM_MAIN_VSA(vm->vsync_len) | DSIM_MAIN_HSA(vm->hsync_len); - DSI_WRITE(dsi, DSIM_MSYNC_REG, reg); + exynos_dsi_write(dsi, DSIM_MSYNC_REG, reg); } reg = DSIM_MAIN_HRESOL(vm->hactive, num_bits_resol) | DSIM_MAIN_VRESOL(vm->vactive, num_bits_resol); - DSI_WRITE(dsi, DSIM_MDRESOL_REG, reg); + exynos_dsi_write(dsi, DSIM_MDRESOL_REG, reg); dev_dbg(dsi->dev, "LCD size = %dx%d\n", vm->hactive, vm->vactive); } @@ -898,12 +934,12 @@ static void exynos_dsi_set_display_enable(struct exynos_dsi *dsi, bool enable) { u32 reg; - reg = DSI_READ(dsi, DSIM_MDRESOL_REG); + reg = exynos_dsi_read(dsi, DSIM_MDRESOL_REG); if (enable) reg |= DSIM_MAIN_STAND_BY; else reg &= ~DSIM_MAIN_STAND_BY; - DSI_WRITE(dsi, DSIM_MDRESOL_REG, reg); + exynos_dsi_write(dsi, DSIM_MDRESOL_REG, reg); } static int exynos_dsi_wait_for_hdr_fifo(struct exynos_dsi *dsi) @@ -911,7 +947,7 @@ static int exynos_dsi_wait_for_hdr_fifo(struct exynos_dsi *dsi) int timeout = 2000; do { - u32 reg = DSI_READ(dsi, DSIM_FIFOCTRL_REG); + u32 reg = exynos_dsi_read(dsi, DSIM_FIFOCTRL_REG); if (!(reg & DSIM_SFR_HEADER_FULL)) return 0; @@ -925,34 +961,35 @@ static int exynos_dsi_wait_for_hdr_fifo(struct exynos_dsi *dsi) static void exynos_dsi_set_cmd_lpm(struct exynos_dsi *dsi, bool lpm) { - u32 v = DSI_READ(dsi, DSIM_ESCMODE_REG); + u32 v = exynos_dsi_read(dsi, DSIM_ESCMODE_REG); if (lpm) v |= DSIM_CMD_LPDT_LP; else v &= ~DSIM_CMD_LPDT_LP; - DSI_WRITE(dsi, DSIM_ESCMODE_REG, v); + exynos_dsi_write(dsi, DSIM_ESCMODE_REG, v); } static void exynos_dsi_force_bta(struct exynos_dsi *dsi) { - u32 v = DSI_READ(dsi, DSIM_ESCMODE_REG); + u32 v = exynos_dsi_read(dsi, DSIM_ESCMODE_REG); v |= DSIM_FORCE_BTA; - DSI_WRITE(dsi, DSIM_ESCMODE_REG, v); + exynos_dsi_write(dsi, DSIM_ESCMODE_REG, v); } static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi, struct exynos_dsi_transfer *xfer) { struct device *dev = dsi->dev; - const u8 *payload = xfer->tx_payload + xfer->tx_done; - u16 length = xfer->tx_len - xfer->tx_done; + struct mipi_dsi_packet *pkt = &xfer->packet; + const u8 *payload = pkt->payload + xfer->tx_done; + u16 length = pkt->payload_length - xfer->tx_done; bool first = !xfer->tx_done; u32 reg; dev_dbg(dev, "< xfer %p: tx len %u, done %u, rx len %u, done %u\n", - xfer, xfer->tx_len, xfer->tx_done, xfer->rx_len, xfer->rx_done); + xfer, length, xfer->tx_done, xfer->rx_len, xfer->rx_done); if (length > DSI_TX_FIFO_SIZE) length = DSI_TX_FIFO_SIZE; @@ -961,9 +998,8 @@ static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi, /* Send payload */ while (length >= 4) { - reg = (payload[3] << 24) | (payload[2] << 16) - | (payload[1] << 8) | payload[0]; - DSI_WRITE(dsi, DSIM_PAYLOAD_REG, reg); + reg = get_unaligned_le32(payload); + exynos_dsi_write(dsi, DSIM_PAYLOAD_REG, reg); payload += 4; length -= 4; } @@ -978,10 +1014,7 @@ static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi, /* Fall through */ case 1: reg |= payload[0]; - DSI_WRITE(dsi, DSIM_PAYLOAD_REG, reg); - break; - case 0: - /* Do nothing */ + exynos_dsi_write(dsi, DSIM_PAYLOAD_REG, reg); break; } @@ -989,7 +1022,7 @@ static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi, if (!first) return; - reg = (xfer->data[1] << 16) | (xfer->data[0] << 8) | xfer->data_id; + reg = get_unaligned_le32(pkt->header); if (exynos_dsi_wait_for_hdr_fifo(dsi)) { dev_err(dev, "waiting for header FIFO timed out\n"); return; @@ -1001,7 +1034,7 @@ static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi, dsi->state ^= DSIM_STATE_CMD_LPM; } - DSI_WRITE(dsi, DSIM_PKTHDR_REG, reg); + exynos_dsi_write(dsi, DSIM_PKTHDR_REG, reg); if (xfer->flags & MIPI_DSI_MSG_REQ_ACK) exynos_dsi_force_bta(dsi); @@ -1017,7 +1050,7 @@ static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi, u32 reg; if (first) { - reg = DSI_READ(dsi, DSIM_RXFIFO_REG); + reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG); switch (reg & 0x3f) { case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE: @@ -1056,7 +1089,7 @@ static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi, /* Receive payload */ while (length >= 4) { - reg = DSI_READ(dsi, DSIM_RXFIFO_REG); + reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG); payload[0] = (reg >> 0) & 0xff; payload[1] = (reg >> 8) & 0xff; payload[2] = (reg >> 16) & 0xff; @@ -1066,7 +1099,7 @@ static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi, } if (length) { - reg = DSI_READ(dsi, DSIM_RXFIFO_REG); + reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG); switch (length) { case 3: payload[2] = (reg >> 16) & 0xff; @@ -1085,7 +1118,7 @@ static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi, clear_fifo: length = DSI_RX_FIFO_SIZE / 4; do { - reg = DSI_READ(dsi, DSIM_RXFIFO_REG); + reg = exynos_dsi_read(dsi, DSIM_RXFIFO_REG); if (reg == DSI_RX_FIFO_EMPTY) break; } while (--length); @@ -1110,13 +1143,14 @@ again: spin_unlock_irqrestore(&dsi->transfer_lock, flags); - if (xfer->tx_len && xfer->tx_done == xfer->tx_len) + if (xfer->packet.payload_length && + xfer->tx_done == xfer->packet.payload_length) /* waiting for RX */ return; exynos_dsi_send_to_fifo(dsi, xfer); - if (xfer->tx_len || xfer->rx_len) + if (xfer->packet.payload_length || xfer->rx_len) return; xfer->result = 0; @@ -1152,10 +1186,11 @@ static bool exynos_dsi_transfer_finish(struct exynos_dsi *dsi) spin_unlock_irqrestore(&dsi->transfer_lock, flags); dev_dbg(dsi->dev, - "> xfer %p, tx_len %u, tx_done %u, rx_len %u, rx_done %u\n", - xfer, xfer->tx_len, xfer->tx_done, xfer->rx_len, xfer->rx_done); + "> xfer %p, tx_len %zu, tx_done %u, rx_len %u, rx_done %u\n", + xfer, xfer->packet.payload_length, xfer->tx_done, xfer->rx_len, + xfer->rx_done); - if (xfer->tx_done != xfer->tx_len) + if (xfer->tx_done != xfer->packet.payload_length) return true; if (xfer->rx_done != xfer->rx_len) @@ -1226,9 +1261,10 @@ static int exynos_dsi_transfer(struct exynos_dsi *dsi, wait_for_completion_timeout(&xfer->completed, msecs_to_jiffies(DSI_XFER_TIMEOUT_MS)); if (xfer->result == -ETIMEDOUT) { + struct mipi_dsi_packet *pkt = &xfer->packet; exynos_dsi_remove_transfer(dsi, xfer); - dev_err(dsi->dev, "xfer timed out: %*ph %*ph\n", 2, xfer->data, - xfer->tx_len, xfer->tx_payload); + dev_err(dsi->dev, "xfer timed out: %*ph %*ph\n", 4, pkt->header, + (int)pkt->payload_length, pkt->payload); return -ETIMEDOUT; } @@ -1241,20 +1277,20 @@ static irqreturn_t exynos_dsi_irq(int irq, void *dev_id) struct exynos_dsi *dsi = dev_id; u32 status; - status = DSI_READ(dsi, DSIM_INTSRC_REG); + status = exynos_dsi_read(dsi, DSIM_INTSRC_REG); if (!status) { static unsigned long int j; if (printk_timed_ratelimit(&j, 500)) dev_warn(dsi->dev, "spurious interrupt\n"); return IRQ_HANDLED; } - DSI_WRITE(dsi, DSIM_INTSRC_REG, status); + exynos_dsi_write(dsi, DSIM_INTSRC_REG, status); if (status & DSIM_INT_SW_RST_RELEASE) { u32 mask = ~(DSIM_INT_RX_DONE | DSIM_INT_SFR_FIFO_EMPTY | DSIM_INT_SFR_HDR_FIFO_EMPTY | DSIM_INT_FRAME_DONE | DSIM_INT_RX_ECC_ERR | DSIM_INT_SW_RST_RELEASE); - DSI_WRITE(dsi, DSIM_INTMSK_REG, mask); + exynos_dsi_write(dsi, DSIM_INTMSK_REG, mask); complete(&dsi->completed); return IRQ_HANDLED; } @@ -1401,12 +1437,6 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, return 0; } -/* distinguish between short and long DSI packet types */ -static bool exynos_dsi_is_short_dsi_type(u8 type) -{ - return (type & 0x0f) <= 8; -} - static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host, const struct mipi_dsi_msg *msg) { @@ -1424,25 +1454,9 @@ static ssize_t exynos_dsi_host_transfer(struct mipi_dsi_host *host, dsi->state |= DSIM_STATE_INITIALIZED; } - if (msg->tx_len == 0) - return -EINVAL; - - xfer.data_id = msg->type | (msg->channel << 6); - - if (exynos_dsi_is_short_dsi_type(msg->type)) { - const char *tx_buf = msg->tx_buf; - - if (msg->tx_len > 2) - return -EINVAL; - xfer.tx_len = 0; - xfer.data[0] = tx_buf[0]; - xfer.data[1] = (msg->tx_len == 2) ? tx_buf[1] : 0; - } else { - xfer.tx_len = msg->tx_len; - xfer.data[0] = msg->tx_len & 0xff; - xfer.data[1] = msg->tx_len >> 8; - xfer.tx_payload = msg->tx_buf; - } + ret = mipi_dsi_create_packet(&xfer.packet, msg); + if (ret < 0) + return ret; xfer.rx_len = msg->rx_len; xfer.rx_payload = msg->rx_buf; @@ -1597,13 +1611,6 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder) return 0; } -static bool exynos_dsi_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - static void exynos_dsi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -1623,7 +1630,6 @@ static void exynos_dsi_mode_set(struct drm_encoder *encoder, } static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = { - .mode_fixup = exynos_dsi_mode_fixup, .mode_set = exynos_dsi_mode_set, .enable = exynos_dsi_enable, .disable = exynos_dsi_disable, @@ -1782,6 +1788,7 @@ static int exynos_dsi_bind(struct device *dev, struct device *master, bridge = of_drm_find_bridge(dsi->bridge_node); if (bridge) { + encoder->bridge = bridge; drm_bridge_attach(drm_dev, bridge); } |