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