xref: /OK3568_Linux_fs/u-boot/drivers/video/rockchip/rk_mipi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun  * Author: Eric Gao <eric.gao@rock-chips.com>
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * SPDX-License-Identifier: GPL-2.0+
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <clk.h>
10*4882a593Smuzhiyun #include <display.h>
11*4882a593Smuzhiyun #include <dm.h>
12*4882a593Smuzhiyun #include <fdtdec.h>
13*4882a593Smuzhiyun #include <panel.h>
14*4882a593Smuzhiyun #include <regmap.h>
15*4882a593Smuzhiyun #include "rk_mipi.h"
16*4882a593Smuzhiyun #include <syscon.h>
17*4882a593Smuzhiyun #include <asm/gpio.h>
18*4882a593Smuzhiyun #include <asm/hardware.h>
19*4882a593Smuzhiyun #include <asm/io.h>
20*4882a593Smuzhiyun #include <dm/uclass-internal.h>
21*4882a593Smuzhiyun #include <linux/kernel.h>
22*4882a593Smuzhiyun #include <asm/arch/clock.h>
23*4882a593Smuzhiyun #include <asm/arch/cru_rk3399.h>
24*4882a593Smuzhiyun #include <asm/arch/grf_rk3399.h>
25*4882a593Smuzhiyun #include <asm/arch/rockchip_mipi_dsi.h>
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
28*4882a593Smuzhiyun 
rk_mipi_read_timing(struct udevice * dev,struct display_timing * timing)29*4882a593Smuzhiyun int rk_mipi_read_timing(struct udevice *dev,
30*4882a593Smuzhiyun 			struct display_timing *timing)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun 	int ret;
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	ret = fdtdec_decode_display_timing(gd->fdt_blob, dev_of_offset(dev),
35*4882a593Smuzhiyun 					 0, timing);
36*4882a593Smuzhiyun 	if (ret) {
37*4882a593Smuzhiyun 		debug("%s: Failed to decode display timing (ret=%d)\n",
38*4882a593Smuzhiyun 		      __func__, ret);
39*4882a593Smuzhiyun 		return -EINVAL;
40*4882a593Smuzhiyun 	}
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	return 0;
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun /*
46*4882a593Smuzhiyun  * Register write function used only for mipi dsi controller.
47*4882a593Smuzhiyun  * Parameter:
48*4882a593Smuzhiyun  *  @regs: mipi controller address
49*4882a593Smuzhiyun  *  @reg: combination of regaddr(16bit)|bitswidth(8bit)|offset(8bit) you can
50*4882a593Smuzhiyun  *        use define in rk_mipi.h directly for this parameter
51*4882a593Smuzhiyun  *  @val: value that will be write to specified bits of register
52*4882a593Smuzhiyun  */
rk_mipi_dsi_write(uintptr_t regs,u32 reg,u32 val)53*4882a593Smuzhiyun static void rk_mipi_dsi_write(uintptr_t regs, u32 reg, u32 val)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun 	u32 dat;
56*4882a593Smuzhiyun 	u32 mask;
57*4882a593Smuzhiyun 	u32 offset = (reg >> OFFSET_SHIFT) & 0xff;
58*4882a593Smuzhiyun 	u32 bits = (reg >> BITS_SHIFT) & 0xff;
59*4882a593Smuzhiyun 	uintptr_t addr = (reg >> ADDR_SHIFT) + regs;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	/* Mask for specifiled bits,the corresponding bits will be clear */
62*4882a593Smuzhiyun 	mask = ~((0xffffffff << offset) & (0xffffffff >> (32 - offset - bits)));
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	/* Make sure val in the available range */
65*4882a593Smuzhiyun 	val &= ~(0xffffffff << bits);
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	/* Get register's original val */
68*4882a593Smuzhiyun 	dat = readl(addr);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	/* Clear specified bits */
71*4882a593Smuzhiyun 	dat &= mask;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	/* Fill specified bits */
74*4882a593Smuzhiyun 	dat |= val << offset;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	writel(dat, addr);
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
rk_mipi_dsi_enable(struct udevice * dev,const struct display_timing * timing)79*4882a593Smuzhiyun int rk_mipi_dsi_enable(struct udevice *dev,
80*4882a593Smuzhiyun 		       const struct display_timing *timing)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun 	int node, timing_node;
83*4882a593Smuzhiyun 	int val;
84*4882a593Smuzhiyun 	struct rk_mipi_priv *priv = dev_get_priv(dev);
85*4882a593Smuzhiyun 	uintptr_t regs = priv->regs;
86*4882a593Smuzhiyun 	u32 txbyte_clk = priv->txbyte_clk;
87*4882a593Smuzhiyun 	u32 txesc_clk = priv->txesc_clk;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	txesc_clk = txbyte_clk/(txbyte_clk/txesc_clk + 1);
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	/* Set Display timing parameter */
92*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, VID_HSA_TIME, timing->hsync_len.typ);
93*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, VID_HBP_TIME, timing->hback_porch.typ);
94*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, VID_HLINE_TIME, (timing->hsync_len.typ
95*4882a593Smuzhiyun 			  + timing->hback_porch.typ + timing->hactive.typ
96*4882a593Smuzhiyun 			  + timing->hfront_porch.typ));
97*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, VID_VSA_LINES, timing->vsync_len.typ);
98*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, VID_VBP_LINES, timing->vback_porch.typ);
99*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, VID_VFP_LINES, timing->vfront_porch.typ);
100*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, VID_ACTIVE_LINES, timing->vactive.typ);
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	/* Set Signal Polarity */
103*4882a593Smuzhiyun 	val = (timing->flags & DISPLAY_FLAGS_HSYNC_LOW) ? 1 : 0;
104*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, HSYNC_ACTIVE_LOW, val);
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	val = (timing->flags & DISPLAY_FLAGS_VSYNC_LOW) ? 1 : 0;
107*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, VSYNC_ACTIVE_LOW, val);
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	val = (timing->flags & DISPLAY_FLAGS_DE_LOW) ? 1 : 0;
110*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, DISPLAY_FLAGS_DE_LOW, val);
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	val = (timing->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) ? 1 : 0;
113*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, COLORM_ACTIVE_LOW, val);
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	/* Set video mode */
116*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, CMD_VIDEO_MODE, VIDEO_MODE);
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	/* Set video mode transmission type as burst mode */
119*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, VID_MODE_TYPE, BURST_MODE);
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	/* Set pix num in a video package */
122*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, VID_PKT_SIZE, 0x4b0);
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	/* Set dpi color coding depth 24 bit */
125*4882a593Smuzhiyun 	timing_node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(dev),
126*4882a593Smuzhiyun 									 "display-timings");
127*4882a593Smuzhiyun 	node = fdt_first_subnode(gd->fdt_blob, timing_node);
128*4882a593Smuzhiyun 	val = fdtdec_get_int(gd->fdt_blob, node, "bits-per-pixel", -1);
129*4882a593Smuzhiyun 	switch (val) {
130*4882a593Smuzhiyun 	case 16:
131*4882a593Smuzhiyun 		rk_mipi_dsi_write(regs, DPI_COLOR_CODING, DPI_16BIT_CFG_1);
132*4882a593Smuzhiyun 		break;
133*4882a593Smuzhiyun 	case 24:
134*4882a593Smuzhiyun 		rk_mipi_dsi_write(regs, DPI_COLOR_CODING, DPI_24BIT);
135*4882a593Smuzhiyun 		break;
136*4882a593Smuzhiyun 	case 30:
137*4882a593Smuzhiyun 		rk_mipi_dsi_write(regs, DPI_COLOR_CODING, DPI_30BIT);
138*4882a593Smuzhiyun 		break;
139*4882a593Smuzhiyun 	default:
140*4882a593Smuzhiyun 		rk_mipi_dsi_write(regs, DPI_COLOR_CODING, DPI_24BIT);
141*4882a593Smuzhiyun 	}
142*4882a593Smuzhiyun 	/* Enable low power mode */
143*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, LP_CMD_EN, 1);
144*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, LP_HFP_EN, 1);
145*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, LP_VACT_EN, 1);
146*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, LP_VFP_EN, 1);
147*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, LP_VBP_EN, 1);
148*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, LP_VSA_EN, 1);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	/* Division for timeout counter clk */
151*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, TO_CLK_DIVISION, 0x0a);
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	/* Tx esc clk division from txbyte clk */
154*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, TX_ESC_CLK_DIVISION, txbyte_clk/txesc_clk);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	/* Timeout count for hs<->lp transation between Line period */
157*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, HSTX_TO_CNT, 0x3e8);
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	/* Phy State transfer timing */
160*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_STOP_WAIT_TIME, 32);
161*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_TXREQUESTCLKHS, 1);
162*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_HS2LP_TIME, 0x14);
163*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_LP2HS_TIME, 0x10);
164*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, MAX_RD_TIME, 0x2710);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	/* Power on */
167*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, SHUTDOWNZ, 1);
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	return 0;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun /* rk mipi dphy write function. It is used to write test data to dphy */
rk_mipi_phy_write(uintptr_t regs,unsigned char test_code,unsigned char * test_data,unsigned char size)173*4882a593Smuzhiyun static void rk_mipi_phy_write(uintptr_t regs, unsigned char test_code,
174*4882a593Smuzhiyun 			      unsigned char *test_data, unsigned char size)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun 	int i = 0;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	/* Write Test code */
179*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_TESTCLK, 1);
180*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_TESTDIN, test_code);
181*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_TESTEN, 1);
182*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_TESTCLK, 0);
183*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_TESTEN, 0);
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	/* Write Test data */
186*4882a593Smuzhiyun 	for (i = 0; i < size; i++) {
187*4882a593Smuzhiyun 		rk_mipi_dsi_write(regs, PHY_TESTCLK, 0);
188*4882a593Smuzhiyun 		rk_mipi_dsi_write(regs, PHY_TESTDIN, test_data[i]);
189*4882a593Smuzhiyun 		rk_mipi_dsi_write(regs, PHY_TESTCLK, 1);
190*4882a593Smuzhiyun 	}
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun /*
194*4882a593Smuzhiyun  * Mipi dphy config function. Calculate the suitable prediv, feedback div,
195*4882a593Smuzhiyun  * fsfreqrang value ,cap ,lpf and so on according to the given pix clk rate,
196*4882a593Smuzhiyun  * and then enable phy.
197*4882a593Smuzhiyun  */
rk_mipi_phy_enable(struct udevice * dev)198*4882a593Smuzhiyun int rk_mipi_phy_enable(struct udevice *dev)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun 	int i;
201*4882a593Smuzhiyun 	struct rk_mipi_priv *priv = dev_get_priv(dev);
202*4882a593Smuzhiyun 	uintptr_t regs = priv->regs;
203*4882a593Smuzhiyun 	u64 fbdiv;
204*4882a593Smuzhiyun 	u64 prediv = 1;
205*4882a593Smuzhiyun 	u32 max_fbdiv = 512;
206*4882a593Smuzhiyun 	u32 max_prediv, min_prediv;
207*4882a593Smuzhiyun 	u64 ddr_clk = priv->phy_clk;
208*4882a593Smuzhiyun 	u32 refclk = priv->ref_clk;
209*4882a593Smuzhiyun 	u32 remain = refclk;
210*4882a593Smuzhiyun 	unsigned char test_data[2] = {0};
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	int freq_rang[][2] = {
213*4882a593Smuzhiyun 		{90, 0x01},   {100, 0x10},  {110, 0x20},  {130, 0x01},
214*4882a593Smuzhiyun 		{140, 0x11},  {150, 0x21},  {170, 0x02},  {180, 0x12},
215*4882a593Smuzhiyun 		{200, 0x22},  {220, 0x03},  {240, 0x13},  {250, 0x23},
216*4882a593Smuzhiyun 		{270, 0x04},  {300, 0x14},  {330, 0x05},  {360, 0x15},
217*4882a593Smuzhiyun 		{400, 0x25},  {450, 0x06},  {500, 0x16},  {550, 0x07},
218*4882a593Smuzhiyun 		{600, 0x17},  {650, 0x08},  {700, 0x18},  {750, 0x09},
219*4882a593Smuzhiyun 		{800, 0x19},  {850, 0x29},  {900, 0x39},  {950, 0x0a},
220*4882a593Smuzhiyun 		{1000, 0x1a}, {1050, 0x2a}, {1100, 0x3a}, {1150, 0x0b},
221*4882a593Smuzhiyun 		{1200, 0x1b}, {1250, 0x2b}, {1300, 0x3b}, {1350, 0x0c},
222*4882a593Smuzhiyun 		{1400, 0x1c}, {1450, 0x2c}, {1500, 0x3c}
223*4882a593Smuzhiyun 	};
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	/* Shutdown mode */
226*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_SHUTDOWNZ, 0);
227*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_RSTZ, 0);
228*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_TESTCLR, 1);
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	/* Pll locking */
231*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_TESTCLR, 0);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	/* config cp and lfp */
234*4882a593Smuzhiyun 	test_data[0] = 0x80 | (ddr_clk / (200 * MHz)) << 3 | 0x3;
235*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_PLL_VCORANGE_VCOCAP, test_data, 1);
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	test_data[0] = 0x8;
238*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_PLL_CPCTRL, test_data, 1);
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	test_data[0] = 0x80 | 0x40;
241*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_PLL_LPF_CP, test_data, 1);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	/* select the suitable value for fsfreqrang reg */
244*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(freq_rang); i++) {
245*4882a593Smuzhiyun 		if (ddr_clk / (MHz) >= freq_rang[i][0])
246*4882a593Smuzhiyun 			break;
247*4882a593Smuzhiyun 	}
248*4882a593Smuzhiyun 	if (i == ARRAY_SIZE(freq_rang)) {
249*4882a593Smuzhiyun 		debug("%s: Dphy freq out of range!\n", __func__);
250*4882a593Smuzhiyun 		return -EINVAL;
251*4882a593Smuzhiyun 	}
252*4882a593Smuzhiyun 	test_data[0] = freq_rang[i][1] << 1;
253*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_HS_RX_LANE0, test_data, 1);
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	/*
256*4882a593Smuzhiyun 	 * Calculate the best ddrclk and it's corresponding div value. If the
257*4882a593Smuzhiyun 	 * given pixelclock is great than 250M, ddrclk will be fix 1500M.
258*4882a593Smuzhiyun 	 * Otherwise,
259*4882a593Smuzhiyun 	 * it's equal to ddr_clk= pixclk * 6. 40MHz >= refclk / prediv >= 5MHz
260*4882a593Smuzhiyun 	 * according to spec.
261*4882a593Smuzhiyun 	 */
262*4882a593Smuzhiyun 	max_prediv = (refclk / (5 * MHz));
263*4882a593Smuzhiyun 	min_prediv = ((refclk / (40 * MHz)) ? (refclk / (40 * MHz) + 1) : 1);
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	debug("%s: DEBUG: max_prediv=%u, min_prediv=%u\n", __func__, max_prediv,
266*4882a593Smuzhiyun 	      min_prediv);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 	if (max_prediv < min_prediv) {
269*4882a593Smuzhiyun 		debug("%s: Invalid refclk value\n", __func__);
270*4882a593Smuzhiyun 		return -EINVAL;
271*4882a593Smuzhiyun 	}
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	/* Calculate the best refclk and feedback division value for dphy pll */
274*4882a593Smuzhiyun 	for (i = min_prediv; i < max_prediv; i++) {
275*4882a593Smuzhiyun 		if ((ddr_clk * i % refclk < remain) &&
276*4882a593Smuzhiyun 		    (ddr_clk * i / refclk) < max_fbdiv) {
277*4882a593Smuzhiyun 			prediv = i;
278*4882a593Smuzhiyun 			remain = ddr_clk * i % refclk;
279*4882a593Smuzhiyun 		}
280*4882a593Smuzhiyun 	}
281*4882a593Smuzhiyun 	fbdiv = ddr_clk * prediv / refclk;
282*4882a593Smuzhiyun 	ddr_clk = refclk * fbdiv / prediv;
283*4882a593Smuzhiyun 	priv->phy_clk = ddr_clk;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	debug("%s: DEBUG: refclk=%u, refclk=%llu, fbdiv=%llu, phyclk=%llu\n",
286*4882a593Smuzhiyun 	      __func__, refclk, prediv, fbdiv, ddr_clk);
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	/* config prediv and feedback reg */
289*4882a593Smuzhiyun 	test_data[0] = prediv - 1;
290*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_PLL_INPUT_DIV_RAT, test_data, 1);
291*4882a593Smuzhiyun 	test_data[0] = (fbdiv - 1) & 0x1f;
292*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_PLL_LOOP_DIV_RAT, test_data, 1);
293*4882a593Smuzhiyun 	test_data[0] = (fbdiv - 1) >> 5 | 0x80;
294*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_PLL_LOOP_DIV_RAT, test_data, 1);
295*4882a593Smuzhiyun 	test_data[0] = 0x30;
296*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_PLL_INPUT_LOOP_DIV_RAT, test_data, 1);
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	/* rest config */
299*4882a593Smuzhiyun 	test_data[0] = 0x4d;
300*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_BANDGAP_BIAS_CTRL, test_data, 1);
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	test_data[0] = 0x3d;
303*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_TERMINATION_CTRL, test_data, 1);
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	test_data[0] = 0xdf;
306*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_TERMINATION_CTRL, test_data, 1);
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	test_data[0] =  0x7;
309*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_AFE_BIAS_BANDGAP_ANOLOG, test_data, 1);
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	test_data[0] = 0x80 | 0x7;
312*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_AFE_BIAS_BANDGAP_ANOLOG, test_data, 1);
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	test_data[0] = 0x80 | 15;
315*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_HSTXDATALANEREQUSETSTATETIME,
316*4882a593Smuzhiyun 			  test_data, 1);
317*4882a593Smuzhiyun 	test_data[0] = 0x80 | 85;
318*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_HSTXDATALANEPREPARESTATETIME,
319*4882a593Smuzhiyun 			  test_data, 1);
320*4882a593Smuzhiyun 	test_data[0] = 0x40 | 10;
321*4882a593Smuzhiyun 	rk_mipi_phy_write(regs, CODE_HSTXDATALANEHSZEROSTATETIME,
322*4882a593Smuzhiyun 			  test_data, 1);
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	/* enter into stop mode */
325*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, N_LANES, 0x03);
326*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_ENABLECLK, 1);
327*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_FORCEPLL, 1);
328*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_SHUTDOWNZ, 1);
329*4882a593Smuzhiyun 	rk_mipi_dsi_write(regs, PHY_RSTZ, 1);
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	return 0;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun 
334