drm/exynos: dsi: add support for Exynos5433
This patch adds support for Exynos5433 mipi dsi. Signed-off-by: Hyungwon Hwang <human.hwang@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com>
This commit is contained in:
		
							parent
							
								
									0ff03fd164
								
							
						
					
					
						commit
						e6f988a458
					
				| @ -6,6 +6,7 @@ Required properties: | ||||
| 		"samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */ | ||||
| 		"samsung,exynos4415-mipi-dsi" /* for Exynos4415 SoC */ | ||||
| 		"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 | ||||
|   - interrupts: should contain DSI interrupt | ||||
|   - clocks: list of clock specifiers, must contain an entry for each required | ||||
|  | ||||
| @ -47,7 +47,7 @@ config DRM_EXYNOS_DPI | ||||
| 
 | ||||
| config DRM_EXYNOS_DSI | ||||
| 	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_PANEL | ||||
| 	default n | ||||
|  | ||||
| @ -132,6 +132,7 @@ | ||||
| #define DSIM_INT_PLL_STABLE		(1 << 31) | ||||
| #define DSIM_INT_SW_RST_RELEASE		(1 << 30) | ||||
| #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_FRAME_DONE		(1 << 24) | ||||
| #define DSIM_INT_RX_TIMEOUT		(1 << 21) | ||||
| @ -180,6 +181,8 @@ | ||||
| 
 | ||||
| /* DSIM_PHYCTRL */ | ||||
| #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 */ | ||||
| #define DSIM_PHYTIMING_LPX(x)		((x) << 8) | ||||
| @ -211,7 +214,9 @@ | ||||
| 					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 { | ||||
| 	EXYNOS_DSI_TX, | ||||
| @ -341,6 +346,30 @@ static unsigned int exynos_reg_ofs[] = { | ||||
| 	[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 { | ||||
| 	RESET_TYPE, | ||||
| 	PLL_TIMER, | ||||
| @ -377,6 +406,24 @@ static unsigned int reg_values[] = { | ||||
| 	[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 = { | ||||
| 	.reg_ofs = exynos_reg_ofs, | ||||
| 	.plltmr_reg = 0x50, | ||||
| @ -422,6 +469,17 @@ static struct exynos_dsi_driver_data exynos5_dsi_driver_data = { | ||||
| 	.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[] = { | ||||
| 	{ .compatible = "samsung,exynos3250-mipi-dsi", | ||||
| 	  .data = &exynos3_dsi_driver_data }, | ||||
| @ -431,6 +489,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,exynos5433-mipi-dsi", | ||||
| 	  .data = &exynos5433_dsi_driver_data }, | ||||
| 	{ } | ||||
| }; | ||||
| 
 | ||||
| @ -682,6 +742,14 @@ static void exynos_dsi_disable_clock(struct exynos_dsi *dsi) | ||||
| 	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) | ||||
| { | ||||
| 	struct exynos_dsi_driver_data *driver_data = dsi->driver_data; | ||||
| @ -754,17 +822,6 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi) | ||||
| 		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 | ||||
| 	 * host controller supports | ||||
| @ -776,8 +833,11 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi) | ||||
| 	if (driver_data->has_clklane_stop && | ||||
| 			dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) { | ||||
| 		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 */ | ||||
| 	timeout = 100; | ||||
| @ -1189,13 +1249,16 @@ static irqreturn_t exynos_dsi_irq(int irq, void *dev_id) | ||||
| 	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); | ||||
| 		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); | ||||
| 		complete(&dsi->completed); | ||||
| 		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; | ||||
| 
 | ||||
| 	if (exynos_dsi_transfer_finish(dsi)) | ||||
| @ -1237,6 +1300,10 @@ static int exynos_dsi_init(struct exynos_dsi *dsi) | ||||
| 
 | ||||
| 	exynos_dsi_reset(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); | ||||
| 	if (driver_data->wait_for_reset) | ||||
| 		exynos_dsi_wait_for_reset(dsi); | ||||
| @ -1811,6 +1878,9 @@ static int exynos_dsi_probe(struct platform_device *pdev) | ||||
| 	dsi->clks = devm_kzalloc(dev, | ||||
| 			sizeof(*dsi->clks) * dsi->driver_data->num_clks, | ||||
| 			GFP_KERNEL); | ||||
| 	if (!dsi->clks) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	for (i = 0; i < dsi->driver_data->num_clks; i++) { | ||||
| 		dsi->clks[i] = devm_clk_get(dev, clk_names[i]); | ||||
| 		if (IS_ERR(dsi->clks[i])) { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user