xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 2010 Intel Corporation
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Software"),
6*4882a593Smuzhiyun  * to deal in the Software without restriction, including without limitation
7*4882a593Smuzhiyun  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
9*4882a593Smuzhiyun  * Software is furnished to do so, subject to the following conditions:
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * The above copyright notice and this permission notice (including the next
12*4882a593Smuzhiyun  * paragraph) shall be included in all copies or substantial portions of the
13*4882a593Smuzhiyun  * Software.
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*4882a593Smuzhiyun  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*4882a593Smuzhiyun  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*4882a593Smuzhiyun  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*4882a593Smuzhiyun  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*4882a593Smuzhiyun  * DEALINGS IN THE SOFTWARE.
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  * Authors:
24*4882a593Smuzhiyun  * jim liu <jim.liu@intel.com>
25*4882a593Smuzhiyun  * Jackie Li<yaodong.li@intel.com>
26*4882a593Smuzhiyun  */
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #include <linux/delay.h>
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #include <drm/drm_simple_kms_helper.h>
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #include "mdfld_dsi_dpi.h"
33*4882a593Smuzhiyun #include "mdfld_dsi_pkg_sender.h"
34*4882a593Smuzhiyun #include "mdfld_output.h"
35*4882a593Smuzhiyun #include "psb_drv.h"
36*4882a593Smuzhiyun #include "tc35876x-dsi-lvds.h"
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output,
39*4882a593Smuzhiyun 								int pipe);
40*4882a593Smuzhiyun 
mdfld_wait_for_HS_DATA_FIFO(struct drm_device * dev,u32 pipe)41*4882a593Smuzhiyun static void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
44*4882a593Smuzhiyun 	int timeout = 0;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	udelay(500);
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	/* This will time out after approximately 2+ seconds */
49*4882a593Smuzhiyun 	while ((timeout < 20000) &&
50*4882a593Smuzhiyun 		(REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) {
51*4882a593Smuzhiyun 		udelay(100);
52*4882a593Smuzhiyun 		timeout++;
53*4882a593Smuzhiyun 	}
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	if (timeout == 20000)
56*4882a593Smuzhiyun 		DRM_INFO("MIPI: HS Data FIFO was never cleared!\n");
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun 
mdfld_wait_for_HS_CTRL_FIFO(struct drm_device * dev,u32 pipe)59*4882a593Smuzhiyun static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun 	u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
62*4882a593Smuzhiyun 	int timeout = 0;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	udelay(500);
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	/* This will time out after approximately 2+ seconds */
67*4882a593Smuzhiyun 	while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg)
68*4882a593Smuzhiyun 					& DSI_FIFO_GEN_HS_CTRL_FULL)) {
69*4882a593Smuzhiyun 		udelay(100);
70*4882a593Smuzhiyun 		timeout++;
71*4882a593Smuzhiyun 	}
72*4882a593Smuzhiyun 	if (timeout == 20000)
73*4882a593Smuzhiyun 		DRM_INFO("MIPI: HS CMD FIFO was never cleared!\n");
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun 
mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device * dev,u32 pipe)76*4882a593Smuzhiyun static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun 	u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
79*4882a593Smuzhiyun 	int timeout = 0;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	udelay(500);
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	/* This will time out after approximately 2+ seconds */
84*4882a593Smuzhiyun 	while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) &
85*4882a593Smuzhiyun 					DPI_FIFO_EMPTY) != DPI_FIFO_EMPTY)) {
86*4882a593Smuzhiyun 		udelay(100);
87*4882a593Smuzhiyun 		timeout++;
88*4882a593Smuzhiyun 	}
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	if (timeout == 20000)
91*4882a593Smuzhiyun 		DRM_ERROR("MIPI: DPI FIFO was never cleared\n");
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
mdfld_wait_for_SPL_PKG_SENT(struct drm_device * dev,u32 pipe)94*4882a593Smuzhiyun static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	u32 intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
97*4882a593Smuzhiyun 	int timeout = 0;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	udelay(500);
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	/* This will time out after approximately 2+ seconds */
102*4882a593Smuzhiyun 	while ((timeout < 20000) && (!(REG_READ(intr_stat_reg)
103*4882a593Smuzhiyun 					& DSI_INTR_STATE_SPL_PKG_SENT))) {
104*4882a593Smuzhiyun 		udelay(100);
105*4882a593Smuzhiyun 		timeout++;
106*4882a593Smuzhiyun 	}
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	if (timeout == 20000)
109*4882a593Smuzhiyun                 DRM_ERROR("MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n");
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun /* For TC35876X */
113*4882a593Smuzhiyun 
dsi_set_device_ready_state(struct drm_device * dev,int state,int pipe)114*4882a593Smuzhiyun static void dsi_set_device_ready_state(struct drm_device *dev, int state,
115*4882a593Smuzhiyun 				int pipe)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun 	REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), !!state, 0, 0);
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun 
dsi_set_pipe_plane_enable_state(struct drm_device * dev,int state,int pipe)120*4882a593Smuzhiyun static void dsi_set_pipe_plane_enable_state(struct drm_device *dev,
121*4882a593Smuzhiyun 							int state, int pipe)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
124*4882a593Smuzhiyun 	u32 pipeconf_reg = PIPEACONF;
125*4882a593Smuzhiyun 	u32 dspcntr_reg = DSPACNTR;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	u32 dspcntr = dev_priv->dspcntr[pipe];
128*4882a593Smuzhiyun 	u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	if (pipe) {
131*4882a593Smuzhiyun 		pipeconf_reg = PIPECCONF;
132*4882a593Smuzhiyun 		dspcntr_reg = DSPCCNTR;
133*4882a593Smuzhiyun 	} else
134*4882a593Smuzhiyun 		mipi &= (~0x03);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	if (state) {
137*4882a593Smuzhiyun 		/*Set up pipe */
138*4882a593Smuzhiyun 		REG_WRITE(pipeconf_reg, BIT(31));
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 		if (REG_BIT_WAIT(pipeconf_reg, 1, 30))
141*4882a593Smuzhiyun 			dev_err(&dev->pdev->dev, "%s: Pipe enable timeout\n",
142*4882a593Smuzhiyun 				__func__);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 		/*Set up display plane */
145*4882a593Smuzhiyun 		REG_WRITE(dspcntr_reg, dspcntr);
146*4882a593Smuzhiyun 	} else {
147*4882a593Smuzhiyun 		u32 dspbase_reg = pipe ? MDFLD_DSPCBASE : MRST_DSPABASE;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 		/* Put DSI lanes to ULPS to disable pipe */
150*4882a593Smuzhiyun 		REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 2, 2, 1);
151*4882a593Smuzhiyun 		REG_READ(MIPI_DEVICE_READY_REG(pipe)); /* posted write? */
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 		/* LP Hold */
154*4882a593Smuzhiyun 		REG_FLD_MOD(MIPI_PORT_CONTROL(pipe), 0, 16, 16);
155*4882a593Smuzhiyun 		REG_READ(MIPI_PORT_CONTROL(pipe)); /* posted write? */
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 		/* Disable display plane */
158*4882a593Smuzhiyun 		REG_FLD_MOD(dspcntr_reg, 0, 31, 31);
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 		/* Flush the plane changes ??? posted write? */
161*4882a593Smuzhiyun 		REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
162*4882a593Smuzhiyun 		REG_READ(dspbase_reg);
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 		/* Disable PIPE */
165*4882a593Smuzhiyun 		REG_FLD_MOD(pipeconf_reg, 0, 31, 31);
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 		if (REG_BIT_WAIT(pipeconf_reg, 0, 30))
168*4882a593Smuzhiyun 			dev_err(&dev->pdev->dev, "%s: Pipe disable timeout\n",
169*4882a593Smuzhiyun 				__func__);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 		if (REG_BIT_WAIT(MIPI_GEN_FIFO_STAT_REG(pipe), 1, 28))
172*4882a593Smuzhiyun 			dev_err(&dev->pdev->dev, "%s: FIFO not empty\n",
173*4882a593Smuzhiyun 				__func__);
174*4882a593Smuzhiyun 	}
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun 
mdfld_dsi_configure_down(struct mdfld_dsi_encoder * dsi_encoder,int pipe)177*4882a593Smuzhiyun static void mdfld_dsi_configure_down(struct mdfld_dsi_encoder *dsi_encoder,
178*4882a593Smuzhiyun 								int pipe)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun 	struct mdfld_dsi_dpi_output *dpi_output =
181*4882a593Smuzhiyun 				MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
182*4882a593Smuzhiyun 	struct mdfld_dsi_config *dsi_config =
183*4882a593Smuzhiyun 				mdfld_dsi_encoder_get_config(dsi_encoder);
184*4882a593Smuzhiyun 	struct drm_device *dev = dsi_config->dev;
185*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	if (!dev_priv->dpi_panel_on[pipe]) {
188*4882a593Smuzhiyun 		dev_err(dev->dev, "DPI panel is already off\n");
189*4882a593Smuzhiyun 		return;
190*4882a593Smuzhiyun 	}
191*4882a593Smuzhiyun 	tc35876x_toshiba_bridge_panel_off(dev);
192*4882a593Smuzhiyun 	tc35876x_set_bridge_reset_state(dev, 1);
193*4882a593Smuzhiyun 	dsi_set_pipe_plane_enable_state(dev, 0, pipe);
194*4882a593Smuzhiyun 	mdfld_dsi_dpi_shut_down(dpi_output, pipe);
195*4882a593Smuzhiyun 	dsi_set_device_ready_state(dev, 0, pipe);
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun 
mdfld_dsi_configure_up(struct mdfld_dsi_encoder * dsi_encoder,int pipe)198*4882a593Smuzhiyun static void mdfld_dsi_configure_up(struct mdfld_dsi_encoder *dsi_encoder,
199*4882a593Smuzhiyun 								int pipe)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun 	struct mdfld_dsi_dpi_output *dpi_output =
202*4882a593Smuzhiyun 				MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
203*4882a593Smuzhiyun 	struct mdfld_dsi_config *dsi_config =
204*4882a593Smuzhiyun 				mdfld_dsi_encoder_get_config(dsi_encoder);
205*4882a593Smuzhiyun 	struct drm_device *dev = dsi_config->dev;
206*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	if (dev_priv->dpi_panel_on[pipe]) {
209*4882a593Smuzhiyun 		dev_err(dev->dev, "DPI panel is already on\n");
210*4882a593Smuzhiyun 		return;
211*4882a593Smuzhiyun 	}
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	/* For resume path sequence */
214*4882a593Smuzhiyun 	mdfld_dsi_dpi_shut_down(dpi_output, pipe);
215*4882a593Smuzhiyun 	dsi_set_device_ready_state(dev, 0, pipe);
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	dsi_set_device_ready_state(dev, 1, pipe);
218*4882a593Smuzhiyun 	tc35876x_set_bridge_reset_state(dev, 0);
219*4882a593Smuzhiyun 	tc35876x_configure_lvds_bridge(dev);
220*4882a593Smuzhiyun 	mdfld_dsi_dpi_turn_on(dpi_output, pipe);  /* Send turn on command */
221*4882a593Smuzhiyun 	dsi_set_pipe_plane_enable_state(dev, 1, pipe);
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun /* End for TC35876X */
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun /* ************************************************************************* *\
226*4882a593Smuzhiyun  * FUNCTION: mdfld_dsi_tpo_ic_init
227*4882a593Smuzhiyun  *
228*4882a593Smuzhiyun  * DESCRIPTION:  This function is called only by mrst_dsi_mode_set and
229*4882a593Smuzhiyun  *               restore_display_registers.  since this function does not
230*4882a593Smuzhiyun  *               acquire the mutex, it is important that the calling function
231*4882a593Smuzhiyun  *               does!
232*4882a593Smuzhiyun \* ************************************************************************* */
mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config * dsi_config,u32 pipe)233*4882a593Smuzhiyun static void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun 	struct drm_device *dev = dsi_config->dev;
236*4882a593Smuzhiyun 	u32 dcsChannelNumber = dsi_config->channel_num;
237*4882a593Smuzhiyun 	u32 gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe);
238*4882a593Smuzhiyun 	u32 gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe);
239*4882a593Smuzhiyun 	u32 gen_ctrl_val = GEN_LONG_WRITE;
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	DRM_INFO("Enter mrst init TPO MIPI display.\n");
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	/* Flip page order */
246*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
247*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x00008036);
248*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
249*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	/* 0xF0 */
252*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
253*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x005a5af0);
254*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
255*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	/* Write protection key */
258*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
259*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x005a5af1);
260*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
261*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	/* 0xFC */
264*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
265*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x005a5afc);
266*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
267*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	/* 0xB7 */
270*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
271*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x770000b7);
272*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
273*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x00000044);
274*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
275*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS));
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	/* 0xB6 */
278*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
279*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x000a0ab6);
280*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
281*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	/* 0xF2 */
284*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
285*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x081010f2);
286*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
287*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x4a070708);
288*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
289*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x000000c5);
290*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
291*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	/* 0xF8 */
294*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
295*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x024003f8);
296*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
297*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x01030a04);
298*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
299*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x0e020220);
300*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
301*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x00000004);
302*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
303*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS));
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	/* 0xE2 */
306*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
307*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x398fc3e2);
308*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
309*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x0000916f);
310*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
311*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS));
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	/* 0xB0 */
314*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
315*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x000000b0);
316*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
317*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	/* 0xF4 */
320*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
321*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x240242f4);
322*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
323*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x78ee2002);
324*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
325*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x2a071050);
326*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
327*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x507fee10);
328*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
329*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x10300710);
330*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
331*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS));
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	/* 0xBA */
334*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
335*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x19fe07ba);
336*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
337*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x101c0a31);
338*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
339*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x00000010);
340*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
341*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	/* 0xBB */
344*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
345*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x28ff07bb);
346*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
347*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x24280a31);
348*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
349*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x00000034);
350*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
351*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	/* 0xFB */
354*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
355*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x535d05fb);
356*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
357*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x1b1a2130);
358*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
359*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x221e180e);
360*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
361*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x131d2120);
362*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
363*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x535d0508);
364*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
365*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x1c1a2131);
366*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
367*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x231f160d);
368*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
369*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x111b2220);
370*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
371*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x535c2008);
372*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
373*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x1f1d2433);
374*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
375*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x2c251a10);
376*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
377*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x2c34372d);
378*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
379*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x00000023);
380*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
381*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	/* 0xFA */
384*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
385*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x525c0bfa);
386*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
387*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x1c1c232f);
388*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
389*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x2623190e);
390*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
391*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x18212625);
392*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
393*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x545d0d0e);
394*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
395*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x1e1d2333);
396*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
397*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x26231a10);
398*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
399*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x1a222725);
400*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
401*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x545d280f);
402*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
403*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x21202635);
404*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
405*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x31292013);
406*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
407*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x31393d33);
408*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
409*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x00000029);
410*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
411*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	/* Set DM */
414*4882a593Smuzhiyun 	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
415*4882a593Smuzhiyun 	REG_WRITE(gen_data_reg, 0x000100f7);
416*4882a593Smuzhiyun 	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
417*4882a593Smuzhiyun 	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun 
mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count,int num_lane,int bpp)420*4882a593Smuzhiyun static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count,
421*4882a593Smuzhiyun 						int num_lane, int bpp)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun 	return (u16)((pixel_clock_count * bpp) / (num_lane * 8));
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun /*
427*4882a593Smuzhiyun  * Calculate the dpi time basing on a given drm mode @mode
428*4882a593Smuzhiyun  * return 0 on success.
429*4882a593Smuzhiyun  * FIXME: I was using proposed mode value for calculation, may need to
430*4882a593Smuzhiyun  * use crtc mode values later
431*4882a593Smuzhiyun  */
mdfld_dsi_dpi_timing_calculation(struct drm_display_mode * mode,struct mdfld_dsi_dpi_timing * dpi_timing,int num_lane,int bpp)432*4882a593Smuzhiyun int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode,
433*4882a593Smuzhiyun 				struct mdfld_dsi_dpi_timing *dpi_timing,
434*4882a593Smuzhiyun 				int num_lane, int bpp)
435*4882a593Smuzhiyun {
436*4882a593Smuzhiyun 	int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive;
437*4882a593Smuzhiyun 	int pclk_vsync, pclk_vfp, pclk_vbp;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	pclk_hactive = mode->hdisplay;
440*4882a593Smuzhiyun 	pclk_hfp = mode->hsync_start - mode->hdisplay;
441*4882a593Smuzhiyun 	pclk_hsync = mode->hsync_end - mode->hsync_start;
442*4882a593Smuzhiyun 	pclk_hbp = mode->htotal - mode->hsync_end;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	pclk_vfp = mode->vsync_start - mode->vdisplay;
445*4882a593Smuzhiyun 	pclk_vsync = mode->vsync_end - mode->vsync_start;
446*4882a593Smuzhiyun 	pclk_vbp = mode->vtotal - mode->vsync_end;
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	/*
449*4882a593Smuzhiyun 	 * byte clock counts were calculated by following formula
450*4882a593Smuzhiyun 	 * bclock_count = pclk_count * bpp / num_lane / 8
451*4882a593Smuzhiyun 	 */
452*4882a593Smuzhiyun 	dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count(
453*4882a593Smuzhiyun 						pclk_hsync, num_lane, bpp);
454*4882a593Smuzhiyun 	dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count(
455*4882a593Smuzhiyun 						pclk_hbp, num_lane, bpp);
456*4882a593Smuzhiyun 	dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count(
457*4882a593Smuzhiyun 						pclk_hfp, num_lane, bpp);
458*4882a593Smuzhiyun 	dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count(
459*4882a593Smuzhiyun 						pclk_hactive, num_lane, bpp);
460*4882a593Smuzhiyun 	dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count(
461*4882a593Smuzhiyun 						pclk_vsync, num_lane, bpp);
462*4882a593Smuzhiyun 	dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count(
463*4882a593Smuzhiyun 						pclk_vbp, num_lane, bpp);
464*4882a593Smuzhiyun 	dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count(
465*4882a593Smuzhiyun 						pclk_vfp, num_lane, bpp);
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	return 0;
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun 
mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config * dsi_config,int pipe)470*4882a593Smuzhiyun void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config,
471*4882a593Smuzhiyun 								int pipe)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	struct drm_device *dev = dsi_config->dev;
474*4882a593Smuzhiyun 	int lane_count = dsi_config->lane_count;
475*4882a593Smuzhiyun 	struct mdfld_dsi_dpi_timing dpi_timing;
476*4882a593Smuzhiyun 	struct drm_display_mode *mode = dsi_config->mode;
477*4882a593Smuzhiyun 	u32 val;
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	/*un-ready device*/
480*4882a593Smuzhiyun 	REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 0, 0, 0);
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	/*init dsi adapter before kicking off*/
483*4882a593Smuzhiyun 	REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018);
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	/*enable all interrupts*/
486*4882a593Smuzhiyun 	REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff);
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	/*set up func_prg*/
489*4882a593Smuzhiyun 	val = lane_count;
490*4882a593Smuzhiyun 	val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET;
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	switch (dsi_config->bpp) {
493*4882a593Smuzhiyun 	case 16:
494*4882a593Smuzhiyun 		val |= DSI_DPI_COLOR_FORMAT_RGB565;
495*4882a593Smuzhiyun 		break;
496*4882a593Smuzhiyun 	case 18:
497*4882a593Smuzhiyun 		val |= DSI_DPI_COLOR_FORMAT_RGB666;
498*4882a593Smuzhiyun 		break;
499*4882a593Smuzhiyun 	case 24:
500*4882a593Smuzhiyun 		val |= DSI_DPI_COLOR_FORMAT_RGB888;
501*4882a593Smuzhiyun 		break;
502*4882a593Smuzhiyun 	default:
503*4882a593Smuzhiyun 		DRM_ERROR("unsupported color format, bpp = %d\n",
504*4882a593Smuzhiyun 							dsi_config->bpp);
505*4882a593Smuzhiyun 	}
506*4882a593Smuzhiyun 	REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), val);
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe),
509*4882a593Smuzhiyun 			(mode->vtotal * mode->htotal * dsi_config->bpp /
510*4882a593Smuzhiyun 				(8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK);
511*4882a593Smuzhiyun 	REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe),
512*4882a593Smuzhiyun 				0xffff & DSI_LP_RX_TIMEOUT_MASK);
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 	/*max value: 20 clock cycles of txclkesc*/
515*4882a593Smuzhiyun 	REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe),
516*4882a593Smuzhiyun 				0x14 & DSI_TURN_AROUND_TIMEOUT_MASK);
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	/*min 21 txclkesc, max: ffffh*/
519*4882a593Smuzhiyun 	REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe),
520*4882a593Smuzhiyun 				0xffff & DSI_RESET_TIMER_MASK);
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 	REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe),
523*4882a593Smuzhiyun 				mode->vdisplay << 16 | mode->hdisplay);
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	/*set DPI timing registers*/
526*4882a593Smuzhiyun 	mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing,
527*4882a593Smuzhiyun 				dsi_config->lane_count, dsi_config->bpp);
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe),
530*4882a593Smuzhiyun 			dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
531*4882a593Smuzhiyun 	REG_WRITE(MIPI_HBP_COUNT_REG(pipe),
532*4882a593Smuzhiyun 			dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
533*4882a593Smuzhiyun 	REG_WRITE(MIPI_HFP_COUNT_REG(pipe),
534*4882a593Smuzhiyun 			dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
535*4882a593Smuzhiyun 	REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe),
536*4882a593Smuzhiyun 			dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
537*4882a593Smuzhiyun 	REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe),
538*4882a593Smuzhiyun 			dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
539*4882a593Smuzhiyun 	REG_WRITE(MIPI_VBP_COUNT_REG(pipe),
540*4882a593Smuzhiyun 			dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
541*4882a593Smuzhiyun 	REG_WRITE(MIPI_VFP_COUNT_REG(pipe),
542*4882a593Smuzhiyun 			dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun 	REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x46);
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	/*min: 7d0 max: 4e20*/
547*4882a593Smuzhiyun 	REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0x000007d0);
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	/*set up video mode*/
550*4882a593Smuzhiyun 	val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE;
551*4882a593Smuzhiyun 	REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), val);
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000);
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 	REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004);
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	/*TODO: figure out how to setup these registers*/
558*4882a593Smuzhiyun 	if (mdfld_get_panel_type(dev, pipe) == TC35876X)
559*4882a593Smuzhiyun 		REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008);
560*4882a593Smuzhiyun 	else
561*4882a593Smuzhiyun 		REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150c3408);
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun 	REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14);
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	if (mdfld_get_panel_type(dev, pipe) == TC35876X)
566*4882a593Smuzhiyun 		tc35876x_set_bridge_reset_state(dev, 0);  /*Pull High Reset */
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 	/*set device ready*/
569*4882a593Smuzhiyun 	REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 1, 0, 0);
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun 
mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output * output,int pipe)572*4882a593Smuzhiyun void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe)
573*4882a593Smuzhiyun {
574*4882a593Smuzhiyun 	struct drm_device *dev = output->dev;
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun 	/* clear special packet sent bit */
577*4882a593Smuzhiyun 	if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
578*4882a593Smuzhiyun 		REG_WRITE(MIPI_INTR_STAT_REG(pipe),
579*4882a593Smuzhiyun 					DSI_INTR_STATE_SPL_PKG_SENT);
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun 	/*send turn on package*/
582*4882a593Smuzhiyun 	REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_TURN_ON);
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	/*wait for SPL_PKG_SENT interrupt*/
585*4882a593Smuzhiyun 	mdfld_wait_for_SPL_PKG_SENT(dev, pipe);
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 	if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
588*4882a593Smuzhiyun 		REG_WRITE(MIPI_INTR_STAT_REG(pipe),
589*4882a593Smuzhiyun 					DSI_INTR_STATE_SPL_PKG_SENT);
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun 	output->panel_on = 1;
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 	/* FIXME the following is disabled to WA the X slow start issue
594*4882a593Smuzhiyun 	   for TMD panel
595*4882a593Smuzhiyun 	if (pipe == 2)
596*4882a593Smuzhiyun 		dev_priv->dpi_panel_on2 = true;
597*4882a593Smuzhiyun 	else if (pipe == 0)
598*4882a593Smuzhiyun 		dev_priv->dpi_panel_on = true; */
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun 
mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output * output,int pipe)601*4882a593Smuzhiyun static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output,
602*4882a593Smuzhiyun 								int pipe)
603*4882a593Smuzhiyun {
604*4882a593Smuzhiyun 	struct drm_device *dev = output->dev;
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	/*if output is on, or mode setting didn't happen, ignore this*/
607*4882a593Smuzhiyun 	if ((!output->panel_on) || output->first_boot) {
608*4882a593Smuzhiyun 		output->first_boot = 0;
609*4882a593Smuzhiyun 		return;
610*4882a593Smuzhiyun 	}
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 	/* Wait for dpi fifo to empty */
613*4882a593Smuzhiyun 	mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe);
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun 	/* Clear the special packet interrupt bit if set */
616*4882a593Smuzhiyun 	if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
617*4882a593Smuzhiyun 		REG_WRITE(MIPI_INTR_STAT_REG(pipe),
618*4882a593Smuzhiyun 					DSI_INTR_STATE_SPL_PKG_SENT);
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 	if (REG_READ(MIPI_DPI_CONTROL_REG(pipe)) == DSI_DPI_CTRL_HS_SHUTDOWN)
621*4882a593Smuzhiyun 		goto shutdown_out;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_SHUTDOWN);
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun shutdown_out:
626*4882a593Smuzhiyun 	output->panel_on = 0;
627*4882a593Smuzhiyun 	output->first_boot = 0;
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 	/* FIXME the following is disabled to WA the X slow start issue
630*4882a593Smuzhiyun 	   for TMD panel
631*4882a593Smuzhiyun 	if (pipe == 2)
632*4882a593Smuzhiyun 		dev_priv->dpi_panel_on2 = false;
633*4882a593Smuzhiyun 	else if (pipe == 0)
634*4882a593Smuzhiyun 		dev_priv->dpi_panel_on = false;	 */
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun 
mdfld_dsi_dpi_set_power(struct drm_encoder * encoder,bool on)637*4882a593Smuzhiyun static void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
638*4882a593Smuzhiyun {
639*4882a593Smuzhiyun 	struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder);
640*4882a593Smuzhiyun 	struct mdfld_dsi_dpi_output *dpi_output =
641*4882a593Smuzhiyun 				MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
642*4882a593Smuzhiyun 	struct mdfld_dsi_config *dsi_config =
643*4882a593Smuzhiyun 				mdfld_dsi_encoder_get_config(dsi_encoder);
644*4882a593Smuzhiyun 	int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
645*4882a593Smuzhiyun 	struct drm_device *dev = dsi_config->dev;
646*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	/*start up display island if it was shutdown*/
649*4882a593Smuzhiyun 	if (!gma_power_begin(dev, true))
650*4882a593Smuzhiyun 		return;
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 	if (on) {
653*4882a593Smuzhiyun 		if (mdfld_get_panel_type(dev, pipe) == TMD_VID)
654*4882a593Smuzhiyun 			mdfld_dsi_dpi_turn_on(dpi_output, pipe);
655*4882a593Smuzhiyun 		else if (mdfld_get_panel_type(dev, pipe) == TC35876X)
656*4882a593Smuzhiyun 			mdfld_dsi_configure_up(dsi_encoder, pipe);
657*4882a593Smuzhiyun 		else {
658*4882a593Smuzhiyun 			/*enable mipi port*/
659*4882a593Smuzhiyun 			REG_WRITE(MIPI_PORT_CONTROL(pipe),
660*4882a593Smuzhiyun 				REG_READ(MIPI_PORT_CONTROL(pipe)) | BIT(31));
661*4882a593Smuzhiyun 			REG_READ(MIPI_PORT_CONTROL(pipe));
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun 			mdfld_dsi_dpi_turn_on(dpi_output, pipe);
664*4882a593Smuzhiyun 			mdfld_dsi_tpo_ic_init(dsi_config, pipe);
665*4882a593Smuzhiyun 		}
666*4882a593Smuzhiyun 		dev_priv->dpi_panel_on[pipe] = true;
667*4882a593Smuzhiyun 	} else {
668*4882a593Smuzhiyun 		if (mdfld_get_panel_type(dev, pipe) == TMD_VID)
669*4882a593Smuzhiyun 			mdfld_dsi_dpi_shut_down(dpi_output, pipe);
670*4882a593Smuzhiyun 		else if (mdfld_get_panel_type(dev, pipe) == TC35876X)
671*4882a593Smuzhiyun 			mdfld_dsi_configure_down(dsi_encoder, pipe);
672*4882a593Smuzhiyun 		else {
673*4882a593Smuzhiyun 			mdfld_dsi_dpi_shut_down(dpi_output, pipe);
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun 			/*disable mipi port*/
676*4882a593Smuzhiyun 			REG_WRITE(MIPI_PORT_CONTROL(pipe),
677*4882a593Smuzhiyun 				REG_READ(MIPI_PORT_CONTROL(pipe)) & ~BIT(31));
678*4882a593Smuzhiyun 			REG_READ(MIPI_PORT_CONTROL(pipe));
679*4882a593Smuzhiyun 		}
680*4882a593Smuzhiyun 		dev_priv->dpi_panel_on[pipe] = false;
681*4882a593Smuzhiyun 	}
682*4882a593Smuzhiyun 	gma_power_end(dev);
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun 
mdfld_dsi_dpi_dpms(struct drm_encoder * encoder,int mode)685*4882a593Smuzhiyun void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode)
686*4882a593Smuzhiyun {
687*4882a593Smuzhiyun 	mdfld_dsi_dpi_set_power(encoder, mode == DRM_MODE_DPMS_ON);
688*4882a593Smuzhiyun }
689*4882a593Smuzhiyun 
mdfld_dsi_dpi_mode_fixup(struct drm_encoder * encoder,const struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)690*4882a593Smuzhiyun bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
691*4882a593Smuzhiyun 				     const struct drm_display_mode *mode,
692*4882a593Smuzhiyun 				     struct drm_display_mode *adjusted_mode)
693*4882a593Smuzhiyun {
694*4882a593Smuzhiyun 	struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder);
695*4882a593Smuzhiyun 	struct mdfld_dsi_config *dsi_config =
696*4882a593Smuzhiyun 				mdfld_dsi_encoder_get_config(dsi_encoder);
697*4882a593Smuzhiyun 	struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 	if (fixed_mode) {
700*4882a593Smuzhiyun 		adjusted_mode->hdisplay = fixed_mode->hdisplay;
701*4882a593Smuzhiyun 		adjusted_mode->hsync_start = fixed_mode->hsync_start;
702*4882a593Smuzhiyun 		adjusted_mode->hsync_end = fixed_mode->hsync_end;
703*4882a593Smuzhiyun 		adjusted_mode->htotal = fixed_mode->htotal;
704*4882a593Smuzhiyun 		adjusted_mode->vdisplay = fixed_mode->vdisplay;
705*4882a593Smuzhiyun 		adjusted_mode->vsync_start = fixed_mode->vsync_start;
706*4882a593Smuzhiyun 		adjusted_mode->vsync_end = fixed_mode->vsync_end;
707*4882a593Smuzhiyun 		adjusted_mode->vtotal = fixed_mode->vtotal;
708*4882a593Smuzhiyun 		adjusted_mode->clock = fixed_mode->clock;
709*4882a593Smuzhiyun 		drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
710*4882a593Smuzhiyun 	}
711*4882a593Smuzhiyun 	return true;
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun 
mdfld_dsi_dpi_prepare(struct drm_encoder * encoder)714*4882a593Smuzhiyun void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder)
715*4882a593Smuzhiyun {
716*4882a593Smuzhiyun 	mdfld_dsi_dpi_set_power(encoder, false);
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun 
mdfld_dsi_dpi_commit(struct drm_encoder * encoder)719*4882a593Smuzhiyun void mdfld_dsi_dpi_commit(struct drm_encoder *encoder)
720*4882a593Smuzhiyun {
721*4882a593Smuzhiyun 	mdfld_dsi_dpi_set_power(encoder, true);
722*4882a593Smuzhiyun }
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun /* For TC35876X */
725*4882a593Smuzhiyun /* This functionality was implemented in FW in iCDK */
726*4882a593Smuzhiyun /* But removed in DV0 and later. So need to add here. */
mipi_set_properties(struct mdfld_dsi_config * dsi_config,int pipe)727*4882a593Smuzhiyun static void mipi_set_properties(struct mdfld_dsi_config *dsi_config, int pipe)
728*4882a593Smuzhiyun {
729*4882a593Smuzhiyun 	struct drm_device *dev = dsi_config->dev;
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 	REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018);
732*4882a593Smuzhiyun 	REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff);
733*4882a593Smuzhiyun 	REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), 0xffffff);
734*4882a593Smuzhiyun 	REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 0xffffff);
735*4882a593Smuzhiyun 	REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 0x14);
736*4882a593Smuzhiyun 	REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 0xff);
737*4882a593Smuzhiyun 	REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x25);
738*4882a593Smuzhiyun 	REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0xf0);
739*4882a593Smuzhiyun 	REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000);
740*4882a593Smuzhiyun 	REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004);
741*4882a593Smuzhiyun 	REG_WRITE(MIPI_DBI_BW_CTRL_REG(pipe), 0x00000820);
742*4882a593Smuzhiyun 	REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14);
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun 
mdfld_mipi_set_video_timing(struct mdfld_dsi_config * dsi_config,int pipe)745*4882a593Smuzhiyun static void mdfld_mipi_set_video_timing(struct mdfld_dsi_config *dsi_config,
746*4882a593Smuzhiyun 					int pipe)
747*4882a593Smuzhiyun {
748*4882a593Smuzhiyun 	struct drm_device *dev = dsi_config->dev;
749*4882a593Smuzhiyun 	struct mdfld_dsi_dpi_timing dpi_timing;
750*4882a593Smuzhiyun 	struct drm_display_mode *mode = dsi_config->mode;
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun 	mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing,
753*4882a593Smuzhiyun 					dsi_config->lane_count,
754*4882a593Smuzhiyun 					dsi_config->bpp);
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 	REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe),
757*4882a593Smuzhiyun 		mode->vdisplay << 16 | mode->hdisplay);
758*4882a593Smuzhiyun 	REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe),
759*4882a593Smuzhiyun 		dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
760*4882a593Smuzhiyun 	REG_WRITE(MIPI_HBP_COUNT_REG(pipe),
761*4882a593Smuzhiyun 		dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
762*4882a593Smuzhiyun 	REG_WRITE(MIPI_HFP_COUNT_REG(pipe),
763*4882a593Smuzhiyun 		dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
764*4882a593Smuzhiyun 	REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe),
765*4882a593Smuzhiyun 		dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
766*4882a593Smuzhiyun 	REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe),
767*4882a593Smuzhiyun 		dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
768*4882a593Smuzhiyun 	REG_WRITE(MIPI_VBP_COUNT_REG(pipe),
769*4882a593Smuzhiyun 		dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
770*4882a593Smuzhiyun 	REG_WRITE(MIPI_VFP_COUNT_REG(pipe),
771*4882a593Smuzhiyun 		dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun 
mdfld_mipi_config(struct mdfld_dsi_config * dsi_config,int pipe)774*4882a593Smuzhiyun static void mdfld_mipi_config(struct mdfld_dsi_config *dsi_config, int pipe)
775*4882a593Smuzhiyun {
776*4882a593Smuzhiyun 	struct drm_device *dev = dsi_config->dev;
777*4882a593Smuzhiyun 	int lane_count = dsi_config->lane_count;
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun 	if (pipe) {
780*4882a593Smuzhiyun 		REG_WRITE(MIPI_PORT_CONTROL(0), 0x00000002);
781*4882a593Smuzhiyun 		REG_WRITE(MIPI_PORT_CONTROL(2), 0x80000000);
782*4882a593Smuzhiyun 	} else {
783*4882a593Smuzhiyun 		REG_WRITE(MIPI_PORT_CONTROL(0), 0x80010000);
784*4882a593Smuzhiyun 		REG_WRITE(MIPI_PORT_CONTROL(2), 0x00);
785*4882a593Smuzhiyun 	}
786*4882a593Smuzhiyun 
787*4882a593Smuzhiyun 	REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150A600F);
788*4882a593Smuzhiyun 	REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), 0x0000000F);
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun 	/* lane_count = 3 */
791*4882a593Smuzhiyun 	REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), 0x00000200 | lane_count);
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 	mdfld_mipi_set_video_timing(dsi_config, pipe);
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun 
mdfld_set_pipe_timing(struct mdfld_dsi_config * dsi_config,int pipe)796*4882a593Smuzhiyun static void mdfld_set_pipe_timing(struct mdfld_dsi_config *dsi_config, int pipe)
797*4882a593Smuzhiyun {
798*4882a593Smuzhiyun 	struct drm_device *dev = dsi_config->dev;
799*4882a593Smuzhiyun 	struct drm_display_mode *mode = dsi_config->mode;
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun 	REG_WRITE(HTOTAL_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1));
802*4882a593Smuzhiyun 	REG_WRITE(HBLANK_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1));
803*4882a593Smuzhiyun 	REG_WRITE(HSYNC_A,
804*4882a593Smuzhiyun 		((mode->hsync_end - 1) << 16) | (mode->hsync_start - 1));
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun 	REG_WRITE(VTOTAL_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1));
807*4882a593Smuzhiyun 	REG_WRITE(VBLANK_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1));
808*4882a593Smuzhiyun 	REG_WRITE(VSYNC_A,
809*4882a593Smuzhiyun 		((mode->vsync_end - 1) << 16) | (mode->vsync_start - 1));
810*4882a593Smuzhiyun 
811*4882a593Smuzhiyun 	REG_WRITE(PIPEASRC,
812*4882a593Smuzhiyun 		((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
813*4882a593Smuzhiyun }
814*4882a593Smuzhiyun /* End for TC35876X */
815*4882a593Smuzhiyun 
mdfld_dsi_dpi_mode_set(struct drm_encoder * encoder,struct drm_display_mode * mode,struct drm_display_mode * adjusted_mode)816*4882a593Smuzhiyun void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
817*4882a593Smuzhiyun 				   struct drm_display_mode *mode,
818*4882a593Smuzhiyun 				   struct drm_display_mode *adjusted_mode)
819*4882a593Smuzhiyun {
820*4882a593Smuzhiyun 	struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder);
821*4882a593Smuzhiyun 	struct mdfld_dsi_dpi_output *dpi_output =
822*4882a593Smuzhiyun 					MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
823*4882a593Smuzhiyun 	struct mdfld_dsi_config *dsi_config =
824*4882a593Smuzhiyun 				mdfld_dsi_encoder_get_config(dsi_encoder);
825*4882a593Smuzhiyun 	struct drm_device *dev = dsi_config->dev;
826*4882a593Smuzhiyun 	struct drm_psb_private *dev_priv = dev->dev_private;
827*4882a593Smuzhiyun 	int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
828*4882a593Smuzhiyun 	u32 pipeconf_reg = PIPEACONF;
829*4882a593Smuzhiyun 	u32 dspcntr_reg = DSPACNTR;
830*4882a593Smuzhiyun 	u32 pipeconf, dspcntr;
831*4882a593Smuzhiyun 
832*4882a593Smuzhiyun 	u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun 	if (WARN_ON(pipe < 0))
835*4882a593Smuzhiyun 		return;
836*4882a593Smuzhiyun 
837*4882a593Smuzhiyun 	pipeconf = dev_priv->pipeconf[pipe];
838*4882a593Smuzhiyun 	dspcntr = dev_priv->dspcntr[pipe];
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 	if (pipe) {
841*4882a593Smuzhiyun 		pipeconf_reg = PIPECCONF;
842*4882a593Smuzhiyun 		dspcntr_reg = DSPCCNTR;
843*4882a593Smuzhiyun 	} else {
844*4882a593Smuzhiyun 		if (mdfld_get_panel_type(dev, pipe) == TC35876X)
845*4882a593Smuzhiyun 			mipi &= (~0x03); /* Use all four lanes */
846*4882a593Smuzhiyun 		else
847*4882a593Smuzhiyun 			mipi |= 2;
848*4882a593Smuzhiyun 	}
849*4882a593Smuzhiyun 
850*4882a593Smuzhiyun 	/*start up display island if it was shutdown*/
851*4882a593Smuzhiyun 	if (!gma_power_begin(dev, true))
852*4882a593Smuzhiyun 		return;
853*4882a593Smuzhiyun 
854*4882a593Smuzhiyun 	if (mdfld_get_panel_type(dev, pipe) == TC35876X) {
855*4882a593Smuzhiyun 		/*
856*4882a593Smuzhiyun 		 * The following logic is required to reset the bridge and
857*4882a593Smuzhiyun 		 * configure. This also starts the DSI clock at 200MHz.
858*4882a593Smuzhiyun 		 */
859*4882a593Smuzhiyun 		tc35876x_set_bridge_reset_state(dev, 0);  /*Pull High Reset */
860*4882a593Smuzhiyun 		tc35876x_toshiba_bridge_panel_on(dev);
861*4882a593Smuzhiyun 		udelay(100);
862*4882a593Smuzhiyun 		/* Now start the DSI clock */
863*4882a593Smuzhiyun 		REG_WRITE(MRST_DPLL_A, 0x00);
864*4882a593Smuzhiyun 		REG_WRITE(MRST_FPA0, 0xC1);
865*4882a593Smuzhiyun 		REG_WRITE(MRST_DPLL_A, 0x00800000);
866*4882a593Smuzhiyun 		udelay(500);
867*4882a593Smuzhiyun 		REG_WRITE(MRST_DPLL_A, 0x80800000);
868*4882a593Smuzhiyun 
869*4882a593Smuzhiyun 		if (REG_BIT_WAIT(pipeconf_reg, 1, 29))
870*4882a593Smuzhiyun 			dev_err(&dev->pdev->dev, "%s: DSI PLL lock timeout\n",
871*4882a593Smuzhiyun 				__func__);
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun 		REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008);
874*4882a593Smuzhiyun 
875*4882a593Smuzhiyun 		mipi_set_properties(dsi_config, pipe);
876*4882a593Smuzhiyun 		mdfld_mipi_config(dsi_config, pipe);
877*4882a593Smuzhiyun 		mdfld_set_pipe_timing(dsi_config, pipe);
878*4882a593Smuzhiyun 
879*4882a593Smuzhiyun 		REG_WRITE(DSPABASE, 0x00);
880*4882a593Smuzhiyun 		REG_WRITE(DSPASIZE,
881*4882a593Smuzhiyun 			((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
882*4882a593Smuzhiyun 
883*4882a593Smuzhiyun 		REG_WRITE(DSPACNTR, 0x98000000);
884*4882a593Smuzhiyun 		REG_WRITE(DSPASURF, 0x00);
885*4882a593Smuzhiyun 
886*4882a593Smuzhiyun 		REG_WRITE(VGACNTRL, 0x80000000);
887*4882a593Smuzhiyun 		REG_WRITE(DEVICE_READY_REG, 0x00000001);
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun 		REG_WRITE(MIPI_PORT_CONTROL(pipe), 0x80810000);
890*4882a593Smuzhiyun 	} else {
891*4882a593Smuzhiyun 		/*set up mipi port FIXME: do at init time */
892*4882a593Smuzhiyun 		REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi);
893*4882a593Smuzhiyun 	}
894*4882a593Smuzhiyun 	REG_READ(MIPI_PORT_CONTROL(pipe));
895*4882a593Smuzhiyun 
896*4882a593Smuzhiyun 	if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
897*4882a593Smuzhiyun 		/* NOP */
898*4882a593Smuzhiyun 	} else if (mdfld_get_panel_type(dev, pipe) == TC35876X) {
899*4882a593Smuzhiyun 		/* set up DSI controller DPI interface */
900*4882a593Smuzhiyun 		mdfld_dsi_dpi_controller_init(dsi_config, pipe);
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun 		/* Configure MIPI Bridge and Panel */
903*4882a593Smuzhiyun 		tc35876x_configure_lvds_bridge(dev);
904*4882a593Smuzhiyun 		dev_priv->dpi_panel_on[pipe] = true;
905*4882a593Smuzhiyun 	} else {
906*4882a593Smuzhiyun 		/*turn on DPI interface*/
907*4882a593Smuzhiyun 		mdfld_dsi_dpi_turn_on(dpi_output, pipe);
908*4882a593Smuzhiyun 	}
909*4882a593Smuzhiyun 
910*4882a593Smuzhiyun 	/*set up pipe*/
911*4882a593Smuzhiyun 	REG_WRITE(pipeconf_reg, pipeconf);
912*4882a593Smuzhiyun 	REG_READ(pipeconf_reg);
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun 	/*set up display plane*/
915*4882a593Smuzhiyun 	REG_WRITE(dspcntr_reg, dspcntr);
916*4882a593Smuzhiyun 	REG_READ(dspcntr_reg);
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun 	msleep(20); /* FIXME: this should wait for vblank */
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun 	if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
921*4882a593Smuzhiyun 		/* NOP */
922*4882a593Smuzhiyun 	} else if (mdfld_get_panel_type(dev, pipe) == TC35876X) {
923*4882a593Smuzhiyun 		mdfld_dsi_dpi_turn_on(dpi_output, pipe);
924*4882a593Smuzhiyun 	} else {
925*4882a593Smuzhiyun 		/* init driver ic */
926*4882a593Smuzhiyun 		mdfld_dsi_tpo_ic_init(dsi_config, pipe);
927*4882a593Smuzhiyun 		/*init backlight*/
928*4882a593Smuzhiyun 		mdfld_dsi_brightness_init(dsi_config, pipe);
929*4882a593Smuzhiyun 	}
930*4882a593Smuzhiyun 
931*4882a593Smuzhiyun 	gma_power_end(dev);
932*4882a593Smuzhiyun }
933*4882a593Smuzhiyun 
934*4882a593Smuzhiyun /*
935*4882a593Smuzhiyun  * Init DSI DPI encoder.
936*4882a593Smuzhiyun  * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
937*4882a593Smuzhiyun  * return pointer of newly allocated DPI encoder, NULL on error
938*4882a593Smuzhiyun  */
mdfld_dsi_dpi_init(struct drm_device * dev,struct mdfld_dsi_connector * dsi_connector,const struct panel_funcs * p_funcs)939*4882a593Smuzhiyun struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
940*4882a593Smuzhiyun 				struct mdfld_dsi_connector *dsi_connector,
941*4882a593Smuzhiyun 				const struct panel_funcs *p_funcs)
942*4882a593Smuzhiyun {
943*4882a593Smuzhiyun 	struct mdfld_dsi_dpi_output *dpi_output = NULL;
944*4882a593Smuzhiyun 	struct mdfld_dsi_config *dsi_config;
945*4882a593Smuzhiyun 	struct drm_connector *connector = NULL;
946*4882a593Smuzhiyun 	struct drm_encoder *encoder = NULL;
947*4882a593Smuzhiyun 	int pipe;
948*4882a593Smuzhiyun 	u32 data;
949*4882a593Smuzhiyun 	int ret;
950*4882a593Smuzhiyun 
951*4882a593Smuzhiyun 	pipe = dsi_connector->pipe;
952*4882a593Smuzhiyun 
953*4882a593Smuzhiyun 	if (mdfld_get_panel_type(dev, pipe) != TC35876X) {
954*4882a593Smuzhiyun 		dsi_config = mdfld_dsi_get_config(dsi_connector);
955*4882a593Smuzhiyun 
956*4882a593Smuzhiyun 		/* panel hard-reset */
957*4882a593Smuzhiyun 		if (p_funcs->reset) {
958*4882a593Smuzhiyun 			ret = p_funcs->reset(dev, pipe);
959*4882a593Smuzhiyun 			if (ret) {
960*4882a593Smuzhiyun 				DRM_ERROR("Panel %d hard-reset failed\n", pipe);
961*4882a593Smuzhiyun 				return NULL;
962*4882a593Smuzhiyun 			}
963*4882a593Smuzhiyun 		}
964*4882a593Smuzhiyun 
965*4882a593Smuzhiyun 		/* panel drvIC init */
966*4882a593Smuzhiyun 		if (p_funcs->drv_ic_init)
967*4882a593Smuzhiyun 			p_funcs->drv_ic_init(dsi_config, pipe);
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun 		/* panel power mode detect */
970*4882a593Smuzhiyun 		ret = mdfld_dsi_get_power_mode(dsi_config, &data, false);
971*4882a593Smuzhiyun 		if (ret) {
972*4882a593Smuzhiyun 			DRM_ERROR("Panel %d get power mode failed\n", pipe);
973*4882a593Smuzhiyun 			dsi_connector->status = connector_status_disconnected;
974*4882a593Smuzhiyun 		} else {
975*4882a593Smuzhiyun 			DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
976*4882a593Smuzhiyun 			dsi_connector->status = connector_status_connected;
977*4882a593Smuzhiyun 		}
978*4882a593Smuzhiyun 	}
979*4882a593Smuzhiyun 
980*4882a593Smuzhiyun 	dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL);
981*4882a593Smuzhiyun 	if (!dpi_output) {
982*4882a593Smuzhiyun 		DRM_ERROR("No memory\n");
983*4882a593Smuzhiyun 		return NULL;
984*4882a593Smuzhiyun 	}
985*4882a593Smuzhiyun 
986*4882a593Smuzhiyun 	dpi_output->panel_on = 0;
987*4882a593Smuzhiyun 	dpi_output->dev = dev;
988*4882a593Smuzhiyun 	if (mdfld_get_panel_type(dev, pipe) != TC35876X)
989*4882a593Smuzhiyun 		dpi_output->p_funcs = p_funcs;
990*4882a593Smuzhiyun 	dpi_output->first_boot = 1;
991*4882a593Smuzhiyun 
992*4882a593Smuzhiyun 	/*get fixed mode*/
993*4882a593Smuzhiyun 	dsi_config = mdfld_dsi_get_config(dsi_connector);
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun 	/*create drm encoder object*/
996*4882a593Smuzhiyun 	connector = &dsi_connector->base.base;
997*4882a593Smuzhiyun 	encoder = &dpi_output->base.base.base;
998*4882a593Smuzhiyun 	drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_LVDS);
999*4882a593Smuzhiyun 	drm_encoder_helper_add(encoder,
1000*4882a593Smuzhiyun 				p_funcs->encoder_helper_funcs);
1001*4882a593Smuzhiyun 
1002*4882a593Smuzhiyun 	/*attach to given connector*/
1003*4882a593Smuzhiyun 	drm_connector_attach_encoder(connector, encoder);
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun 	/*set possible crtcs and clones*/
1006*4882a593Smuzhiyun 	if (dsi_connector->pipe) {
1007*4882a593Smuzhiyun 		encoder->possible_crtcs = (1 << 2);
1008*4882a593Smuzhiyun 		encoder->possible_clones = 0;
1009*4882a593Smuzhiyun 	} else {
1010*4882a593Smuzhiyun 		encoder->possible_crtcs = (1 << 0);
1011*4882a593Smuzhiyun 		encoder->possible_clones = 0;
1012*4882a593Smuzhiyun 	}
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun 	dsi_connector->base.encoder = &dpi_output->base.base;
1015*4882a593Smuzhiyun 
1016*4882a593Smuzhiyun 	return &dpi_output->base;
1017*4882a593Smuzhiyun }
1018