提交 e6f988a4 编写于 作者: H Hyungwon Hwang 提交者: Inki Dae

drm/exynos: dsi: add support for Exynos5433

This patch adds support for Exynos5433 mipi dsi.
Signed-off-by: NHyungwon Hwang <human.hwang@samsung.com>
Signed-off-by: NInki Dae <inki.dae@samsung.com>
上级 0ff03fd1
...@@ -6,6 +6,7 @@ Required properties: ...@@ -6,6 +6,7 @@ Required properties:
"samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */ "samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */
"samsung,exynos4415-mipi-dsi" /* for Exynos4415 SoC */ "samsung,exynos4415-mipi-dsi" /* for Exynos4415 SoC */
"samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */ "samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */
"samsung,exynos5433-mipi-dsi" /* for Exynos5433 SoCs */
- reg: physical base address and length of the registers set for the device - reg: physical base address and length of the registers set for the device
- interrupts: should contain DSI interrupt - interrupts: should contain DSI interrupt
- clocks: list of clock specifiers, must contain an entry for each required - clocks: list of clock specifiers, must contain an entry for each required
......
...@@ -47,7 +47,7 @@ config DRM_EXYNOS_DPI ...@@ -47,7 +47,7 @@ config DRM_EXYNOS_DPI
config DRM_EXYNOS_DSI config DRM_EXYNOS_DSI
bool "EXYNOS DRM MIPI-DSI driver support" bool "EXYNOS DRM MIPI-DSI driver support"
depends on DRM_EXYNOS && (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON) depends on DRM_EXYNOS && (DRM_EXYNOS_FIMD || DRM_EXYNOS5433_DECON || DRM_EXYNOS7_DECON)
select DRM_MIPI_DSI select DRM_MIPI_DSI
select DRM_PANEL select DRM_PANEL
default n default n
......
...@@ -132,6 +132,7 @@ ...@@ -132,6 +132,7 @@
#define DSIM_INT_PLL_STABLE (1 << 31) #define DSIM_INT_PLL_STABLE (1 << 31)
#define DSIM_INT_SW_RST_RELEASE (1 << 30) #define DSIM_INT_SW_RST_RELEASE (1 << 30)
#define DSIM_INT_SFR_FIFO_EMPTY (1 << 29) #define DSIM_INT_SFR_FIFO_EMPTY (1 << 29)
#define DSIM_INT_SFR_HDR_FIFO_EMPTY (1 << 28)
#define DSIM_INT_BTA (1 << 25) #define DSIM_INT_BTA (1 << 25)
#define DSIM_INT_FRAME_DONE (1 << 24) #define DSIM_INT_FRAME_DONE (1 << 24)
#define DSIM_INT_RX_TIMEOUT (1 << 21) #define DSIM_INT_RX_TIMEOUT (1 << 21)
...@@ -180,6 +181,8 @@ ...@@ -180,6 +181,8 @@
/* DSIM_PHYCTRL */ /* DSIM_PHYCTRL */
#define DSIM_PHYCTRL_ULPS_EXIT(x) (((x) & 0x1ff) << 0) #define DSIM_PHYCTRL_ULPS_EXIT(x) (((x) & 0x1ff) << 0)
#define DSIM_PHYCTRL_B_DPHYCTL_VREG_LP (1 << 30)
#define DSIM_PHYCTRL_B_DPHYCTL_SLEW_UP (1 << 14)
/* DSIM_PHYTIMING */ /* DSIM_PHYTIMING */
#define DSIM_PHYTIMING_LPX(x) ((x) << 8) #define DSIM_PHYTIMING_LPX(x) ((x) << 8)
...@@ -211,7 +214,9 @@ ...@@ -211,7 +214,9 @@
REG_ADDR((dsi), (reg_idx))) REG_ADDR((dsi), (reg_idx)))
#define DSI_READ(dsi, reg_idx) readl(REG_ADDR((dsi), (reg_idx))) #define DSI_READ(dsi, reg_idx) readl(REG_ADDR((dsi), (reg_idx)))
static char *clk_names[2] = { "bus_clk", "sclk_mipi" }; static char *clk_names[5] = { "bus_clk", "sclk_mipi",
"phyclk_mipidphy0_bitclkdiv8", "phyclk_mipidphy0_rxclkesc0",
"sclk_rgb_vclk_to_dsim0" };
enum exynos_dsi_transfer_type { enum exynos_dsi_transfer_type {
EXYNOS_DSI_TX, EXYNOS_DSI_TX,
...@@ -341,6 +346,30 @@ static unsigned int exynos_reg_ofs[] = { ...@@ -341,6 +346,30 @@ static unsigned int exynos_reg_ofs[] = {
[DSIM_PHYTIMING2_REG] = 0x6c, [DSIM_PHYTIMING2_REG] = 0x6c,
}; };
static unsigned int exynos5433_reg_ofs[] = {
[DSIM_STATUS_REG] = 0x04,
[DSIM_SWRST_REG] = 0x0C,
[DSIM_CLKCTRL_REG] = 0x10,
[DSIM_TIMEOUT_REG] = 0x14,
[DSIM_CONFIG_REG] = 0x18,
[DSIM_ESCMODE_REG] = 0x1C,
[DSIM_MDRESOL_REG] = 0x20,
[DSIM_MVPORCH_REG] = 0x24,
[DSIM_MHPORCH_REG] = 0x28,
[DSIM_MSYNC_REG] = 0x2C,
[DSIM_INTSRC_REG] = 0x34,
[DSIM_INTMSK_REG] = 0x38,
[DSIM_PKTHDR_REG] = 0x3C,
[DSIM_PAYLOAD_REG] = 0x40,
[DSIM_RXFIFO_REG] = 0x44,
[DSIM_FIFOCTRL_REG] = 0x4C,
[DSIM_PLLCTRL_REG] = 0x94,
[DSIM_PHYCTRL_REG] = 0xA4,
[DSIM_PHYTIMING_REG] = 0xB4,
[DSIM_PHYTIMING1_REG] = 0xB8,
[DSIM_PHYTIMING2_REG] = 0xBC,
};
enum reg_value_idx { enum reg_value_idx {
RESET_TYPE, RESET_TYPE,
PLL_TIMER, PLL_TIMER,
...@@ -377,6 +406,24 @@ static unsigned int reg_values[] = { ...@@ -377,6 +406,24 @@ static unsigned int reg_values[] = {
[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0b), [PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0b),
}; };
static unsigned int exynos5433_reg_values[] = {
[RESET_TYPE] = DSIM_FUNCRST,
[PLL_TIMER] = 22200,
[STOP_STATE_CNT] = 0xa,
[PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0x190),
[PHYCTRL_VREG_LP] = DSIM_PHYCTRL_B_DPHYCTL_VREG_LP,
[PHYCTRL_SLEW_UP] = DSIM_PHYCTRL_B_DPHYCTL_SLEW_UP,
[PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x07),
[PHYTIMING_HS_EXIT] = DSIM_PHYTIMING_HS_EXIT(0x0c),
[PHYTIMING_CLK_PREPARE] = DSIM_PHYTIMING1_CLK_PREPARE(0x09),
[PHYTIMING_CLK_ZERO] = DSIM_PHYTIMING1_CLK_ZERO(0x2d),
[PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0e),
[PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x09),
[PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x0b),
[PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x10),
[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0c),
};
static struct exynos_dsi_driver_data exynos3_dsi_driver_data = { static struct exynos_dsi_driver_data exynos3_dsi_driver_data = {
.reg_ofs = exynos_reg_ofs, .reg_ofs = exynos_reg_ofs,
.plltmr_reg = 0x50, .plltmr_reg = 0x50,
...@@ -422,6 +469,17 @@ static struct exynos_dsi_driver_data exynos5_dsi_driver_data = { ...@@ -422,6 +469,17 @@ static struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
.reg_values = reg_values, .reg_values = reg_values,
}; };
static struct exynos_dsi_driver_data exynos5433_dsi_driver_data = {
.reg_ofs = exynos5433_reg_ofs,
.plltmr_reg = 0xa0,
.has_clklane_stop = 1,
.num_clks = 5,
.max_freq = 1500,
.wait_for_reset = 0,
.num_bits_resol = 12,
.reg_values = exynos5433_reg_values,
};
static struct of_device_id exynos_dsi_of_match[] = { static struct of_device_id exynos_dsi_of_match[] = {
{ .compatible = "samsung,exynos3250-mipi-dsi", { .compatible = "samsung,exynos3250-mipi-dsi",
.data = &exynos3_dsi_driver_data }, .data = &exynos3_dsi_driver_data },
...@@ -431,6 +489,8 @@ static struct of_device_id exynos_dsi_of_match[] = { ...@@ -431,6 +489,8 @@ static struct of_device_id exynos_dsi_of_match[] = {
.data = &exynos4415_dsi_driver_data }, .data = &exynos4415_dsi_driver_data },
{ .compatible = "samsung,exynos5410-mipi-dsi", { .compatible = "samsung,exynos5410-mipi-dsi",
.data = &exynos5_dsi_driver_data }, .data = &exynos5_dsi_driver_data },
{ .compatible = "samsung,exynos5433-mipi-dsi",
.data = &exynos5433_dsi_driver_data },
{ } { }
}; };
...@@ -682,6 +742,14 @@ static void exynos_dsi_disable_clock(struct exynos_dsi *dsi) ...@@ -682,6 +742,14 @@ static void exynos_dsi_disable_clock(struct exynos_dsi *dsi)
DSI_WRITE(dsi, DSIM_PLLCTRL_REG, reg); 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);
reg |= (DSIM_NUM_OF_DATA_LANE(dsi->lanes - 1) | DSIM_LANE_EN_CLK |
DSIM_LANE_EN(lane));
DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
}
static int exynos_dsi_init_link(struct exynos_dsi *dsi) static int exynos_dsi_init_link(struct exynos_dsi *dsi)
{ {
struct exynos_dsi_driver_data *driver_data = dsi->driver_data; struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
...@@ -754,17 +822,6 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi) ...@@ -754,17 +822,6 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
return -EINVAL; return -EINVAL;
} }
reg |= DSIM_NUM_OF_DATA_LANE(dsi->lanes - 1);
DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
reg |= DSIM_LANE_EN_CLK;
DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
lanes_mask = BIT(dsi->lanes) - 1;
reg |= DSIM_LANE_EN(lanes_mask);
DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
/* /*
* Use non-continuous clock mode if the periparal wants and * Use non-continuous clock mode if the periparal wants and
* host controller supports * host controller supports
...@@ -776,8 +833,11 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi) ...@@ -776,8 +833,11 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
if (driver_data->has_clklane_stop && if (driver_data->has_clklane_stop &&
dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) { dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) {
reg |= DSIM_CLKLANE_STOP; reg |= DSIM_CLKLANE_STOP;
DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
} }
DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
lanes_mask = BIT(dsi->lanes) - 1;
exynos_dsi_enable_lane(dsi, lanes_mask);
/* Check clock and data lane state are stop state */ /* Check clock and data lane state are stop state */
timeout = 100; timeout = 100;
...@@ -1189,13 +1249,16 @@ static irqreturn_t exynos_dsi_irq(int irq, void *dev_id) ...@@ -1189,13 +1249,16 @@ static irqreturn_t exynos_dsi_irq(int irq, void *dev_id)
DSI_WRITE(dsi, DSIM_INTSRC_REG, status); DSI_WRITE(dsi, DSIM_INTSRC_REG, status);
if (status & DSIM_INT_SW_RST_RELEASE) { if (status & DSIM_INT_SW_RST_RELEASE) {
u32 mask = ~(DSIM_INT_RX_DONE | DSIM_INT_SFR_FIFO_EMPTY); 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); DSI_WRITE(dsi, DSIM_INTMSK_REG, mask);
complete(&dsi->completed); complete(&dsi->completed);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
if (!(status & (DSIM_INT_RX_DONE | DSIM_INT_SFR_FIFO_EMPTY))) if (!(status & (DSIM_INT_RX_DONE | DSIM_INT_SFR_FIFO_EMPTY |
DSIM_INT_FRAME_DONE | DSIM_INT_PLL_STABLE)))
return IRQ_HANDLED; return IRQ_HANDLED;
if (exynos_dsi_transfer_finish(dsi)) if (exynos_dsi_transfer_finish(dsi))
...@@ -1237,6 +1300,10 @@ static int exynos_dsi_init(struct exynos_dsi *dsi) ...@@ -1237,6 +1300,10 @@ static int exynos_dsi_init(struct exynos_dsi *dsi)
exynos_dsi_reset(dsi); exynos_dsi_reset(dsi);
exynos_dsi_enable_irq(dsi); exynos_dsi_enable_irq(dsi);
if (driver_data->reg_values[RESET_TYPE] == DSIM_FUNCRST)
exynos_dsi_enable_lane(dsi, BIT(dsi->lanes) - 1);
exynos_dsi_enable_clock(dsi); exynos_dsi_enable_clock(dsi);
if (driver_data->wait_for_reset) if (driver_data->wait_for_reset)
exynos_dsi_wait_for_reset(dsi); exynos_dsi_wait_for_reset(dsi);
...@@ -1811,6 +1878,9 @@ static int exynos_dsi_probe(struct platform_device *pdev) ...@@ -1811,6 +1878,9 @@ static int exynos_dsi_probe(struct platform_device *pdev)
dsi->clks = devm_kzalloc(dev, dsi->clks = devm_kzalloc(dev,
sizeof(*dsi->clks) * dsi->driver_data->num_clks, sizeof(*dsi->clks) * dsi->driver_data->num_clks,
GFP_KERNEL); GFP_KERNEL);
if (!dsi->clks)
return -ENOMEM;
for (i = 0; i < dsi->driver_data->num_clks; i++) { for (i = 0; i < dsi->driver_data->num_clks; i++) {
dsi->clks[i] = devm_clk_get(dev, clk_names[i]); dsi->clks[i] = devm_clk_get(dev, clk_names[i]);
if (IS_ERR(dsi->clks[i])) { if (IS_ERR(dsi->clks[i])) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册