[15/59] drm/kmb: Part5 of Mipi Tx Intitialization
diff mbox series

Message ID 1593552491-23698-16-git-send-email-anitha.chrisanthus@intel.com
State New
Headers show
Series
  • Add support for Keem Bay DRM driver
Related show

Commit Message

Chrisanthus, Anitha June 30, 2020, 9:27 p.m. UTC
This is part1 of DPHY initialization.

v2: remove kmb_write() as the function provides no benefit over
calling writel() directly.

Signed-off-by: Anitha Chrisanthus <anitha.chrisanthus@intel.com>
Reviewed-by: Bob Paauwe <bob.j.paauwe@intel.com>
---
 drivers/gpu/drm/kmb/kmb_drv.h  |   5 -
 drivers/gpu/drm/kmb/kmb_dsi.c  | 346 ++++++++++++++++++++++++++++++++++++++---
 drivers/gpu/drm/kmb/kmb_dsi.h  |  10 ++
 drivers/gpu/drm/kmb/kmb_regs.h |  48 +++++-
 4 files changed, 376 insertions(+), 33 deletions(-)

Patch
diff mbox series

diff --git a/drivers/gpu/drm/kmb/kmb_drv.h b/drivers/gpu/drm/kmb/kmb_drv.h
index ba5b3e0..434be1a 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.h
+++ b/drivers/gpu/drm/kmb/kmb_drv.h
@@ -84,11 +84,6 @@  static inline void kmb_write_bits(struct kmb_drm_private *lcd,
 }
 #endif
 
-static inline void kmb_write(void *reg, u32 value)
-{
-	writel(value, reg);
-}
-
 static inline void kmb_write_lcd(unsigned int reg, u32 value)
 {
 	writel(value, (LCD_BASE_ADDR + reg));
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index adcfe81..d6cd1f9 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -47,6 +47,13 @@ 
 #define MIPI_TX_REF_CLK_KHZ         24000
 #define MIPI_TX_CFG_CLK_KHZ         24000
 
+/*DPHY Tx test codes*/
+#define TEST_CODE_HS_FREQ_RANGE_CFG		0x44
+#define TEST_CODE_PLL_ANALOG_PROG		0x1F
+#define TEST_CODE_SLEW_RATE_OVERRIDE_CTRL	0xA0
+#define TEST_CODE_SLEW_RATE_DDL_LOOP_CTRL	0xA3
+#define TEST_CODE_SLEW_RATE_DDL_CYCLES		0xA4
+
 /*
  * These are added here only temporarily for testing,
  * these will eventually go to the device tree sections,
@@ -107,6 +114,77 @@  struct mipi_ctrl_cfg mipi_tx_init_cfg = {
 
 };
 
+typedef struct{
+	uint16_t default_bit_rate_mbps;
+	uint8_t hsfreqrange_code;
+} mipi_hs_freq_range_cfg;
+
+static mipi_hs_freq_range_cfg
+	mipi_hs_freq_range[MIPI_DPHY_DEFAULT_BIT_RATES] = {
+	{.default_bit_rate_mbps = 80, .hsfreqrange_code = 0x00},
+	{.default_bit_rate_mbps = 90, .hsfreqrange_code = 0x10},
+	{.default_bit_rate_mbps = 100, .hsfreqrange_code = 0x20},
+	{.default_bit_rate_mbps = 110, .hsfreqrange_code = 0x30},
+	{.default_bit_rate_mbps = 120, .hsfreqrange_code = 0x01},
+	{.default_bit_rate_mbps = 130, .hsfreqrange_code = 0x11},
+	{.default_bit_rate_mbps = 140, .hsfreqrange_code = 0x21},
+	{.default_bit_rate_mbps = 150, .hsfreqrange_code = 0x31},
+	{.default_bit_rate_mbps = 160, .hsfreqrange_code = 0x02},
+	{.default_bit_rate_mbps = 170, .hsfreqrange_code = 0x12},
+	{.default_bit_rate_mbps = 180, .hsfreqrange_code = 0x22},
+	{.default_bit_rate_mbps = 190, .hsfreqrange_code = 0x32},
+	{.default_bit_rate_mbps = 205, .hsfreqrange_code = 0x03},
+	{.default_bit_rate_mbps = 220, .hsfreqrange_code = 0x13},
+	{.default_bit_rate_mbps = 235, .hsfreqrange_code = 0x23},
+	{.default_bit_rate_mbps = 250, .hsfreqrange_code = 0x33},
+	{.default_bit_rate_mbps = 275, .hsfreqrange_code = 0x04},
+	{.default_bit_rate_mbps = 300, .hsfreqrange_code = 0x14},
+	{.default_bit_rate_mbps = 325, .hsfreqrange_code = 0x25},
+	{.default_bit_rate_mbps = 350, .hsfreqrange_code = 0x35},
+	{.default_bit_rate_mbps = 400, .hsfreqrange_code = 0x05},
+	{.default_bit_rate_mbps = 450, .hsfreqrange_code = 0x16},
+	{.default_bit_rate_mbps = 500, .hsfreqrange_code = 0x26},
+	{.default_bit_rate_mbps = 550, .hsfreqrange_code = 0x37},
+	{.default_bit_rate_mbps = 600, .hsfreqrange_code = 0x07},
+	{.default_bit_rate_mbps = 650, .hsfreqrange_code = 0x18},
+	{.default_bit_rate_mbps = 700, .hsfreqrange_code = 0x28},
+	{.default_bit_rate_mbps = 750, .hsfreqrange_code = 0x39},
+	{.default_bit_rate_mbps = 800, .hsfreqrange_code = 0x09},
+	{.default_bit_rate_mbps = 850, .hsfreqrange_code = 0x19},
+	{.default_bit_rate_mbps = 900, .hsfreqrange_code = 0x29},
+	{.default_bit_rate_mbps = 1000, .hsfreqrange_code = 0x0A},
+	{.default_bit_rate_mbps = 1050, .hsfreqrange_code = 0x1A},
+	{.default_bit_rate_mbps = 1100, .hsfreqrange_code = 0x2A},
+	{.default_bit_rate_mbps = 1150, .hsfreqrange_code = 0x3B},
+	{.default_bit_rate_mbps = 1200, .hsfreqrange_code = 0x0B},
+	{.default_bit_rate_mbps = 1250, .hsfreqrange_code = 0x1B},
+	{.default_bit_rate_mbps = 1300, .hsfreqrange_code = 0x2B},
+	{.default_bit_rate_mbps = 1350, .hsfreqrange_code = 0x3C},
+	{.default_bit_rate_mbps = 1400, .hsfreqrange_code = 0x0C},
+	{.default_bit_rate_mbps = 1450, .hsfreqrange_code = 0x1C},
+	{.default_bit_rate_mbps = 1500, .hsfreqrange_code = 0x2C},
+	{.default_bit_rate_mbps = 1550, .hsfreqrange_code = 0x3D},
+	{.default_bit_rate_mbps = 1600, .hsfreqrange_code = 0x0D},
+	{.default_bit_rate_mbps = 1650, .hsfreqrange_code = 0x1D},
+	{.default_bit_rate_mbps = 1700, .hsfreqrange_code = 0x2E},
+	{.default_bit_rate_mbps = 1750, .hsfreqrange_code = 0x3E},
+	{.default_bit_rate_mbps = 1800, .hsfreqrange_code = 0x0E},
+	{.default_bit_rate_mbps = 1850, .hsfreqrange_code = 0x1E},
+	{.default_bit_rate_mbps = 1900, .hsfreqrange_code = 0x2F},
+	{.default_bit_rate_mbps = 1950, .hsfreqrange_code = 0x3F},
+	{.default_bit_rate_mbps = 2000, .hsfreqrange_code = 0x0F},
+	{.default_bit_rate_mbps = 2050, .hsfreqrange_code = 0x40},
+	{.default_bit_rate_mbps = 2100, .hsfreqrange_code = 0x41},
+	{.default_bit_rate_mbps = 2150, .hsfreqrange_code = 0x42},
+	{.default_bit_rate_mbps = 2200, .hsfreqrange_code = 0x43},
+	{.default_bit_rate_mbps = 2250, .hsfreqrange_code = 0x44},
+	{.default_bit_rate_mbps = 2300, .hsfreqrange_code = 0x45},
+	{.default_bit_rate_mbps = 2350, .hsfreqrange_code = 0x46},
+	{.default_bit_rate_mbps = 2400, .hsfreqrange_code = 0x47},
+	{.default_bit_rate_mbps = 2450, .hsfreqrange_code = 0x48},
+	{.default_bit_rate_mbps = 2500, .hsfreqrange_code = 0x49}
+};
+
 static enum drm_mode_status
 kmb_dsi_mode_valid(struct drm_connector *connector,
 		   struct drm_display_mode *mode)
@@ -344,7 +422,7 @@  static u32 mipi_tx_fg_section_cfg_regs(struct kmb_drm_private *dev_priv,
 		<< MIPI_TX_SECT_DM_SHIFT);	/* bits [24:25] */
 	cfg |= MIPI_TX_SECT_DMA_PACKED;
 	kmb_write_mipi((MIPI_TXm_HS_FGn_SECTo_PH(ctrl_no, frame_id,
-					section)), cfg);
+						 section)), cfg);
 
 	/*unpacked bytes */
 	/*there are 4 frame generators and each fg has 4 sections
@@ -354,8 +432,8 @@  static u32 mipi_tx_fg_section_cfg_regs(struct kmb_drm_private *dev_priv,
 	 *REG_UNPACKED_BYTES1: [15:0]-BYTES2, [31:16]-BYTES3
 	 */
 	reg_adr = MIPI_TXm_HS_FGn_SECT_UNPACKED_BYTES0(ctrl_no, frame_id)
-	+ (section/2)*4;
-	kmb_write_bits_mipi(reg_adr, (section % 2)*16, 16, unpacked_bytes);
+	    + (section / 2) * 4;
+	kmb_write_bits_mipi(reg_adr, (section % 2) * 16, 16, unpacked_bytes);
 
 	/* line config */
 	reg_adr = MIPI_TXm_HS_FGn_SECTo_LINE_CFG(ctrl_no, frame_id, section);
@@ -443,20 +521,20 @@  static void mipi_tx_fg_cfg_regs(struct kmb_drm_private *dev_priv,
 	 *REG_VSYNC_WIDTH0: [15:0]-VSA for channel0, [31:16]-VSA for channel1
 	 *REG_VSYNC_WIDTH1: [15:0]-VSA for channel2, [31:16]-VSA for channel3
 	 */
-	offset = (frame_gen % 2)*16;
-	reg_adr = MIPI_TXm_HS_VSYNC_WIDTHn(ctrl_no, frame_gen/2);
+	offset = (frame_gen % 2) * 16;
+	reg_adr = MIPI_TXm_HS_VSYNC_WIDTHn(ctrl_no, frame_gen / 2);
 	kmb_write_bits_mipi(reg_adr, offset, 16, fg_cfg->vsync_width);
 
-	/*v backporch - same register config like vsync width*/
-	reg_adr = MIPI_TXm_HS_V_BACKPORCHESn(ctrl_no, frame_gen/2);
+	/*v backporch - same register config like vsync width */
+	reg_adr = MIPI_TXm_HS_V_BACKPORCHESn(ctrl_no, frame_gen / 2);
 	kmb_write_bits_mipi(reg_adr, offset, 16, fg_cfg->v_backporch);
 
-	/*v frontporch - same register config like vsync width*/
-	reg_adr = MIPI_TXm_HS_V_FRONTPORCHESn(ctrl_no, frame_gen/2);
+	/*v frontporch - same register config like vsync width */
+	reg_adr = MIPI_TXm_HS_V_FRONTPORCHESn(ctrl_no, frame_gen / 2);
 	kmb_write_bits_mipi(reg_adr, offset, 16, fg_cfg->v_frontporch);
 
-	/*v active - same register config like vsync width*/
-	reg_adr = MIPI_TXm_HS_V_ACTIVEn(ctrl_no, frame_gen/2);
+	/*v active - same register config like vsync width */
+	reg_adr = MIPI_TXm_HS_V_ACTIVEn(ctrl_no, frame_gen / 2);
 	kmb_write_bits_mipi(reg_adr, offset, 16, fg_cfg->v_active);
 
 	/*hsyc width */
@@ -528,7 +606,7 @@  static void mipi_tx_multichannel_fifo_cfg(u8 active_lanes, u8 vchannel_id)
 	u32 fifo_size, fifo_rthreshold;
 	u32 ctrl_no = MIPI_CTRL6;
 
-	/*clear all mc fifo channel sizes and thresholds*/
+	/*clear all mc fifo channel sizes and thresholds */
 	kmb_write_mipi(MIPI_TX_HS_MC_FIFO_CTRL_EN, 0);
 	kmb_write_mipi(MIPI_TX_HS_MC_FIFO_CHAN_ALLOC0, 0);
 	kmb_write_mipi(MIPI_TX_HS_MC_FIFO_CHAN_ALLOC1, 0);
@@ -536,8 +614,7 @@  static void mipi_tx_multichannel_fifo_cfg(u8 active_lanes, u8 vchannel_id)
 	kmb_write_mipi(MIPI_TX_HS_MC_FIFO_RTHRESHOLD1, 0);
 
 	fifo_size = (active_lanes > MIPI_D_LANES_PER_DPHY) ?
-		MIPI_CTRL_4LANE_MAX_MC_FIFO_LOC :
-		MIPI_CTRL_2LANE_MAX_MC_FIFO_LOC;
+	    MIPI_CTRL_4LANE_MAX_MC_FIFO_LOC : MIPI_CTRL_2LANE_MAX_MC_FIFO_LOC;
 	/*MC fifo size for virtual channels 0-3 */
 	/*
 	 *REG_MC_FIFO_CHAN_ALLOC0: [8:0]-channel0, [24:16]-channel1
@@ -545,7 +622,7 @@  static void mipi_tx_multichannel_fifo_cfg(u8 active_lanes, u8 vchannel_id)
 	 */
 	SET_MC_FIFO_CHAN_ALLOC(ctrl_no, vchannel_id, fifo_size);
 
-	/*set threshold to half the fifo size, actual size=size*16*/
+	/*set threshold to half the fifo size, actual size=size*16 */
 	fifo_rthreshold = ((fifo_size + 1) * 8) & BIT_MASK_16;
 	SET_MC_FIFO_RTHRESHOLD(ctrl_no, vchannel_id, fifo_rthreshold);
 
@@ -558,7 +635,7 @@  static void mipi_tx_ctrl_cfg(u8 fg_id, struct mipi_ctrl_cfg *ctrl_cfg)
 	u32 sync_cfg = 0, ctrl = 0, fg_en;
 	u32 ctrl_no = MIPI_CTRL6;
 
-	/*MIPI_TX_HS_SYNC_CFG*/
+	/*MIPI_TX_HS_SYNC_CFG */
 	if (ctrl_cfg->tx_ctrl_cfg.line_sync_pkt_en)
 		sync_cfg |= LINE_SYNC_PKT_ENABLE;
 	if (ctrl_cfg->tx_ctrl_cfg.frame_counter_active)
@@ -587,15 +664,15 @@  static void mipi_tx_ctrl_cfg(u8 fg_id, struct mipi_ctrl_cfg *ctrl_cfg)
 	if (ctrl_cfg->tx_ctrl_cfg.tx_hact_wait_stop)
 		sync_cfg |= HACT_WAIT_STOP(fg_en);
 
-	/* MIPI_TX_HS_CTRL*/
-	ctrl = HS_CTRL_EN | TX_SOURCE; /* type:DSI,source:LCD */
+	/* MIPI_TX_HS_CTRL */
+	ctrl = HS_CTRL_EN | TX_SOURCE;	/* type:DSI,source:LCD */
 	if (ctrl_cfg->tx_ctrl_cfg.tx_dsi_cfg->eotp_en)
 		ctrl |= DSI_EOTP_EN;
 	if (ctrl_cfg->tx_ctrl_cfg.tx_dsi_cfg->hfp_blank_en)
 		ctrl |= DSI_CMD_HFP_EN;
 	ctrl |= LCD_VC(fg_id);
 	ctrl |= ACTIVE_LANES(ctrl_cfg->active_lanes - 1);
-	/*67 ns stop time*/
+	/*67 ns stop time */
 	ctrl |= HSEXIT_CNT(0x43);
 
 	kmb_write_mipi(MIPI_TXm_HS_SYNC_CFG(ctrl_no), sync_cfg);
@@ -603,7 +680,7 @@  static void mipi_tx_ctrl_cfg(u8 fg_id, struct mipi_ctrl_cfg *ctrl_cfg)
 }
 
 static u32 mipi_tx_init_cntrl(struct kmb_drm_private *dev_priv,
-		struct mipi_ctrl_cfg *ctrl_cfg)
+			      struct mipi_ctrl_cfg *ctrl_cfg)
 {
 	u32 ret;
 	u8 active_vchannels = 0;
@@ -644,21 +721,21 @@  static u32 mipi_tx_init_cntrl(struct kmb_drm_private *dev_priv,
 
 		/* set frame specific parameters */
 		mipi_tx_fg_cfg(dev_priv, frame_id, ctrl_cfg->active_lanes,
-				bits_per_pclk,
-				word_count, ctrl_cfg->lane_rate_mbps,
-				ctrl_cfg->tx_ctrl_cfg.frames[frame_id]);
+			       bits_per_pclk,
+			       word_count, ctrl_cfg->lane_rate_mbps,
+			       ctrl_cfg->tx_ctrl_cfg.frames[frame_id]);
 
 		active_vchannels++;
 
 		/*connect lcd to mipi */
-		kmb_write(MSS_CAM_BASE_ADDR + MIPI_TX_MSS_LCD_MIPI_CFG, 1);
+		writel(1, MSS_CAM_BASE_ADDR + MIPI_TX_MSS_LCD_MIPI_CFG);
 
 		break;
 	}
 
 	if (active_vchannels == 0)
 		return -EINVAL;
-	/*Multi-Channel FIFO Configuration*/
+	/*Multi-Channel FIFO Configuration */
 	mipi_tx_multichannel_fifo_cfg(ctrl_cfg->active_lanes, frame_id);
 
 	/*Frame Generator Enable */
@@ -666,6 +743,222 @@  static u32 mipi_tx_init_cntrl(struct kmb_drm_private *dev_priv,
 	return ret;
 }
 
+static void test_mode_send(u32 dphy_no, u32 test_code, u32 test_data)
+{
+	/*send the test code first */
+	/*  Steps for code:
+	 * - set testclk HIGH
+	 * - set testdin with test code
+	 * - set testen HIGH
+	 * - set testclk LOW
+	 * - set testen LOW
+	 */
+	SET_DPHY_TEST_CTRL1_CLK(dphy_no);
+	SET_TEST_DIN0_3(dphy_no, test_code);
+	SET_DPHY_TEST_CTRL1_EN(dphy_no);
+	CLR_DPHY_TEST_CTRL1_CLK(dphy_no);
+	CLR_DPHY_TEST_CTRL1_EN(dphy_no);
+
+	/*send the test data next */
+	/*  Steps for data:
+	 * - set testen LOW
+	 * - set testclk LOW
+	 * - set testdin with data
+	 * - set testclk HIGH
+	 */
+	CLR_DPHY_TEST_CTRL1_EN(dphy_no);
+	CLR_DPHY_TEST_CTRL1_CLK(dphy_no);
+	SET_TEST_DIN0_3(dphy_no, test_data);
+	SET_DPHY_TEST_CTRL1_CLK(dphy_no);
+}
+
+static inline void set_test_mode_src_osc_freq_target_low_bits(u32 dphy_no,
+							      u32 freq)
+{
+	/*typical rise/fall time=166,
+	 * refer Table 1207 databook,sr_osc_freq_target[7:0
+	 */
+	test_mode_send(dphy_no, TEST_CODE_SLEW_RATE_DDL_CYCLES, (freq & 0x7f));
+}
+
+static inline void set_test_mode_slew_rate_calib_en(u32 dphy_no)
+{
+	/*do not bypass slew rate calibration algorithm */
+	/*bits[1:0}=srcal_en_ovr_en, srcal_en_ovr, bit[6]=sr_range */
+	test_mode_send(dphy_no, TEST_CODE_SLEW_RATE_OVERRIDE_CTRL,
+		       (0x03 | (1 << 6)));
+}
+
+static inline void set_test_mode_src_osc_freq_target_hi_bits(u32 dphy_no,
+							     u32 freq)
+{
+	u32 data;
+	/*typical rise/fall time=166, refer Table 1207 databook,
+	 * sr_osc_freq_target[11:7
+	 */
+	data = ((freq >> 6) & 0x1f) | (1 << 7);	/*flag this as high nibble */
+	test_mode_send(dphy_no, TEST_CODE_SLEW_RATE_DDL_CYCLES, data);
+}
+
+static void dphy_init_sequence(struct mipi_ctrl_cfg *cfg, u32 dphy_no,
+			       enum dphy_mode mode)
+{
+	u32 test_code = 0;
+	u32 test_data = 0, val;
+	int i;
+
+	/*Set D-PHY in shutdown mode */
+	/*assert RSTZ signal */
+	CLR_DPHY_INIT_CTRL0(dphy_no, RESETZ);
+	/* assert SHUTDOWNZ signal */
+	CLR_DPHY_INIT_CTRL0(dphy_no, SHUTDOWNZ);
+
+	/*Init D-PHY_n */
+	/*Pulse testclear signal to make sure the d-phy configuration starts
+	 * from a clean base
+	 */
+	SET_DPHY_TEST_CTRL0(dphy_no);
+	/*TODO may need to add 15ns delay here */
+	CLR_DPHY_TEST_CTRL0(dphy_no);
+
+	/*Set mastermacro bit - Master or slave mode */
+	test_code = TEST_CODE_MULTIPLE_PHY_CTRL;
+	/*DPHY has its own clock lane enabled (master) */
+	if (mode == MIPI_DPHY_MASTER)
+		test_data = 0x01;
+	else
+		test_data = 0x00;
+
+	/*send the test code and data */
+	test_mode_send(dphy_no, test_code, test_data);
+
+	/*Set the lane data rate */
+	for (i = 0; i < MIPI_DPHY_DEFAULT_BIT_RATES; i++) {
+		if (mipi_hs_freq_range[i].default_bit_rate_mbps <
+		    cfg->lane_rate_mbps)
+			continue;
+		/* send the test code and data */
+		/*bit[6:0] = hsfreqrange_ovr bit[7] = hsfreqrange_ovr_en */
+		test_mode_send(dphy_no, TEST_CODE_HS_FREQ_RANGE_CFG,
+			       (mipi_hs_freq_range[i].hsfreqrange_code
+				& 0x7f) | (1 << 7));
+		break;
+	}
+	/*
+	 * High-Speed Tx Slew Rate Calibration
+	 * BitRate: > 1.5 Gbps && <= 2.5 Gbps: slew rate control OFF
+	 */
+	if (cfg->lane_rate_mbps > 1500) {
+		/*bypass slew rate calibration algorithm */
+		/*bits[1:0} srcal_en_ovr_en, srcal_en_ovr */
+		test_mode_send(dphy_no, TEST_CODE_SLEW_RATE_OVERRIDE_CTRL,
+			       0x02);
+
+		/* disable slew rate calibration */
+		test_mode_send(dphy_no, TEST_CODE_SLEW_RATE_DDL_LOOP_CTRL,
+			       0x00);
+	} else if (cfg->lane_rate_mbps > 1000) {
+		/*BitRate: > 1 Gbps && <= 1.5 Gbps: - slew rate control ON
+		 * typical rise/fall times: 166 ps
+		 */
+
+		/*do not bypass slew rate calibration algorithm */
+		set_test_mode_slew_rate_calib_en(dphy_no);
+
+		/* enable slew rate calibration */
+		test_mode_send(dphy_no, TEST_CODE_SLEW_RATE_DDL_LOOP_CTRL,
+			       0x01);
+
+		/*set sr_osc_freq_target[6:0] */
+		/*typical rise/fall time=166, refer Table 1207 databook */
+		set_test_mode_src_osc_freq_target_low_bits(dphy_no, 0x72f);
+		/*set sr_osc_freq_target[11:7] */
+		set_test_mode_src_osc_freq_target_hi_bits(dphy_no, 0x72f);
+	} else {
+		/*lane_rate_mbps <= 1000 Mbps */
+		/*BitRate:  <= 1 Gbps:
+		 * - slew rate control ON
+		 * - typical rise/fall times: 225 ps
+		 */
+		/*do not bypass slew rate calibration algorithm */
+		set_test_mode_slew_rate_calib_en(dphy_no);
+		/* enable slew rate calibration */
+		test_mode_send(dphy_no, TEST_CODE_SLEW_RATE_DDL_LOOP_CTRL,
+			       0x01);
+
+		/*typical rise/fall time=255, refer Table 1207 databook */
+		set_test_mode_src_osc_freq_target_low_bits(dphy_no, 0x523);
+		/*set sr_osc_freq_target[11:7] */
+		set_test_mode_src_osc_freq_target_hi_bits(dphy_no, 0x523);
+	}
+
+	/*Set cfgclkfreqrange */
+	val = (((cfg->cfg_clk_khz / 1000) - 17) * 4) & 0x3f;
+	SET_DPHY_FREQ_CTRL0_3(dphy_no, val);
+
+	/*Enable config clk for the corresponding d-phy */
+	kmb_set_bit_mipi(DPHY_CFG_CLK_EN, dphy_no);
+
+	/* PLL setup */
+	if (mode == MIPI_DPHY_MASTER) {
+		/*Set PLL regulator in bypass */
+		test_mode_send(dphy_no, TEST_CODE_PLL_ANALOG_PROG, 0x01);
+
+		/*TODO - PLL Parameters Setup */
+	}
+
+	/*Send NORMAL OPERATION test code */
+	test_mode_send(dphy_no, 0x00, 0x00);
+
+	/* Configure BASEDIR for data lanes
+	 * NOTE: basedir only applies to LANE_0 of each D-PHY.
+	 * The other lanes keep their direction based on the D-PHY type,
+	 * either Rx or Tx.
+	 * bits[5:0]  - BaseDir: 1 = Rx
+	 * bits[9:6] - BaseDir: 0 = Tx
+	 */
+	kmb_clr_bit_mipi(DPHY_INIT_CTRL2, dphy_no);
+
+	/* Enable CLOCK LANE - */
+	/*clock lane should be enabled regardless of the direction set for
+	 * the D-PHY (Rx/Tx)
+	 */
+	kmb_clr_bit_mipi(DPHY_INIT_CTRL2, 12 + dphy_no);
+
+	/* enable DATA LANES */
+	kmb_write_bits_mipi(DPHY_ENABLE, dphy_no * 2, 2,
+			    ((1 << cfg->active_lanes) - 1));
+}
+
+static u32 mipi_tx_init_dphy(struct mipi_ctrl_cfg *cfg)
+{
+	u32 dphy_no = MIPI_DPHY6;
+
+	/*multiple D-PHYs needed */
+	if (cfg->active_lanes > MIPI_DPHY_D_LANES) {
+		/*
+		 *Initialization for Tx aggregation mode is done according to
+		 *http://dub30.ir.intel.com/bugzilla/show_bug.cgi?id=27785#c12:
+		 *a. start init PHY1
+		 *b. poll for PHY1 FSM state LOCK
+		 *   b1. reg addr 0x03[3:0] - state_main[3:0] == 5 (LOCK)
+		 *c. poll for PHY1 calibrations done :
+		 *   c1. termination calibration lower section: addr 0x22[5]
+		 *   - rescal_done
+		 *   c2. slewrate calibration (if data rate < = 1500 Mbps):
+		 *     addr 0xA7[3:2] - srcal_done, sr_finished
+		 *d. start init PHY0
+		 *e. poll for PHY0 stopstate
+		 *f. poll for PHY1 stopstate
+		 */
+		/*PHY #N+1 ('slave') */
+		dphy_init_sequence(cfg, dphy_no + 1, MIPI_DPHY_SLAVE);
+		/*TODO PHY #N master */
+	}
+	/*TODO- Single DPHY */
+	return 0;
+}
+
 void kmb_dsi_init(struct drm_device *dev)
 {
 	struct kmb_dsi *kmb_dsi;
@@ -708,4 +1001,7 @@  void kmb_dsi_init(struct drm_device *dev)
 
 	/* initialize mipi controller */
 	mipi_tx_init_cntrl(dev_priv, &mipi_tx_init_cfg);
+
+	/*d-phy initialization */
+	mipi_tx_init_dphy(&mipi_tx_init_cfg);
 }
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.h b/drivers/gpu/drm/kmb/kmb_dsi.h
index 358373a..d878d27 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.h
+++ b/drivers/gpu/drm/kmb/kmb_dsi.h
@@ -58,6 +58,11 @@  struct kmb_connector {
 #define MIPI_D_LANES_PER_DPHY	2
 #define MIPI_CTRL_2LANE_MAX_MC_FIFO_LOC	255
 #define MIPI_CTRL_4LANE_MAX_MC_FIFO_LOC	511
+#define MIPI_DPHY_D_LANES		2  /* 2 Data Lanes per D-PHY*/
+#define MIPI_DPHY_DEFAULT_BIT_RATES 63
+
+/*DPHY Tx test codes */
+#define TEST_CODE_MULTIPLE_PHY_CTRL	0x03
 
 enum mipi_ctrl_num {
 	MIPI_CTRL0 = 0,
@@ -194,6 +199,11 @@  enum mipi_dsi_data_type {
 	DSI_LP_DT_RESERVED_3F = 0x3f
 };
 
+enum dphy_mode {
+	MIPI_DPHY_SLAVE = 0,
+	MIPI_DPHY_MASTER
+};
+
 struct mipi_data_type_params {
 	uint8_t size_constraint_pixels;
 	uint8_t size_constraint_bytes;
diff --git a/drivers/gpu/drm/kmb/kmb_regs.h b/drivers/gpu/drm/kmb/kmb_regs.h
index 4d6cf3d..5921f709 100644
--- a/drivers/gpu/drm/kmb/kmb_regs.h
+++ b/drivers/gpu/drm/kmb/kmb_regs.h
@@ -27,6 +27,7 @@ 
 #define __KMB_REGS_H__
 
 #define ENABLE					 1
+#define DISABLE					 0
 /*from Data Book section 12.5.8.1 page 4322 */
 #define MIPI_BASE_ADDR                          (void *)(0x20900000)
 /*from Data Book section 12.11.6.1 page 4972 */
@@ -400,8 +401,10 @@ 
 #define MIPI_TX_HS_CTRL				(0x0)
 #define   MIPI_TXm_HS_CTRL(M)			(MIPI_TX_HS_CTRL + HS_OFFSET(M))
 #define   HS_CTRL_EN				(1 << 0)
-#define   HS_CTRL_CSIDSIN			(1 << 2) /*1:CSI 0:DSI*/
-#define   TX_SOURCE				(1 << 3) /*1:LCD, 0:DMA*/
+/*1:CSI 0:DSI */
+#define   HS_CTRL_CSIDSIN			(1 << 2)
+/*1:LCD, 0:DMA */
+#define   TX_SOURCE				(1 << 3)
 #define   ACTIVE_LANES(n)			((n) << 4)
 #define   LCD_VC(ch)				((ch) << 8)
 #define   DSI_EOTP_EN				(1 << 11)
@@ -518,6 +521,45 @@ 
 	kmb_write_bits_mipi(MIPI_TXm_HS_MC_FIFO_RTHRESHOLDn(ctrl, vc/2), \
 			(vc % 2)*16, 16, th)
 
+/* D-PHY regs */
+#define DPHY_ENABLE				(0x100)
+#define DPHY_INIT_CTRL0				(0x104)
+#define   SHUTDOWNZ				0
+#define   RESETZ				12
+#define DPHY_INIT_CTRL2				(0x10c)
+#define   SET_DPHY_INIT_CTRL0(dphy, offset)	\
+					kmb_set_bit_mipi(DPHY_INIT_CTRL0, \
+					(dphy+offset))
+#define   CLR_DPHY_INIT_CTRL0(dphy, offset)	\
+					kmb_clr_bit_mipi(DPHY_INIT_CTRL0, \
+					(dphy+offset))
+#define DPHY_FREQ_CTRL0_3			(0x11c)
+#define   SET_DPHY_FREQ_CTRL0_3(dphy, val)	\
+					kmb_write_bits_mipi(DPHY_FREQ_CTRL0_3 \
+					+ ((dphy/4)*4), (dphy % 4) * 8, \
+					6, val)
+#define DPHY_TEST_CTRL0				(0x154)
+#define   SET_DPHY_TEST_CTRL0(dphy)	kmb_set_bit_mipi(DPHY_TEST_CTRL0, \
+					(dphy))
+#define   CLR_DPHY_TEST_CTRL0(dphy)	kmb_clr_bit_mipi(DPHY_TEST_CTRL0, \
+					(dphy))
+#define DPHY_TEST_CTRL1				(0x158)
+#define   SET_DPHY_TEST_CTRL1_CLK(dphy)	kmb_set_bit_mipi(DPHY_TEST_CTRL1, \
+					(dphy))
+#define   CLR_DPHY_TEST_CTRL1_CLK(dphy)	kmb_clr_bit_mipi(DPHY_TEST_CTRL1, \
+					(dphy))
+#define   SET_DPHY_TEST_CTRL1_EN(dphy)	kmb_set_bit_mipi(DPHY_TEST_CTRL1, \
+					(dphy+12))
+#define   CLR_DPHY_TEST_CTRL1_EN(dphy)	kmb_clr_bit_mipi(DPHY_TEST_CTRL1, \
+					(dphy+12))
+#define DPHY_TEST_DIN0_3			(0x15c)
+#define   SET_TEST_DIN0_3(dphy, val)	kmb_write_mipi(DPHY_TEST_DIN0_3 + \
+					4, ((val) << (((dphy)%4)*8)))
+#define DPHY_TEST_DOUT0_3			(0x168)
+#define   GET_TEST_DOUT0_3(dphy)	(readl(DPHY_TEST_DOUT0_3 + 4) \
+					>> (((dphy)%4)*8) & 0xff)
+#define DPHY_CFG_CLK_EN				(0x18c)
+
 #define MIPI_TX_MSS_LCD_MIPI_CFG		(0x04)
-#define BIT_MASK_16			  (0xffff)
+#define BIT_MASK_16				(0xffff)
 #endif /* __KMB_REGS_H__ */