1 /*******************************************************************
2 *Copyright (c) 2012 by Silicon Motion, Inc. (SMI)
3 *Permission is hereby granted, free of charge, to any person obtaining a copy
4 *of this software and associated documentation files (the "Software"), to deal
5 *in the Software without restriction, including without limitation the rights to
6 *use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 *of the Software, and to permit persons to whom the Software is furnished to
8 *do so, subject to the following conditions:
10 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
12 *OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13 *NONINFRINGEMENT. IN NO EVENT SHALL Mill.Chen and Monk.Liu OR COPYRIGHT
14 *HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
15 *WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
16 *FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
17 *OTHER DEALINGS IN THE SOFTWARE.
18 *******************************************************************/
19 #include "ddk750_help.h"
20 #include "ddk750_reg.h"
21 #include "ddk750_mode.h"
22 #include "ddk750_chip.h"
24 #ifdef CONFIG_FB_LYNXFB_DOMAINS
27 This function takes care extra registers and bit fields required to set
30 Explanation about Display Control register:
31 HW only supports 7 predefined pixel clocks, and clock select is
32 in bit 29:27 of Display Control register.
34 static unsigned long displayControlAdjust_SM750LE(mode_parameter_t
*
42 x
= pModeParam
->horizontal_display_end
;
43 y
= pModeParam
->vertical_display_end
;
45 /* SM750LE has to set up the top-left and bottom-right
47 Note that normal SM750/SM718 only use those two register for
50 POKE32(CRT_AUTO_CENTERING_TL
,
51 (~(0x7FF << CRT_AUTO_CENTERING_TL_TOP_LSB
)) &
52 (~(0x7FF << CRT_AUTO_CENTERING_TL_LEFT_LSB
)), domain
);
55 POKE32(CRT_AUTO_CENTERING_BR
,
56 (~(0x7FF << CRT_AUTO_CENTERING_BR_BOTTOM_LSB
)) |
57 (~(0x7FF << CRT_AUTO_CENTERING_BR_RIGHT_LSB
)), domain
);
58 POKE32(CRT_AUTO_CENTERING_BR
,
59 ((y
- 1) << CRT_AUTO_CENTERING_BR_BOTTOM_LSB
) |
60 ((x
- 1) << CRT_AUTO_CENTERING_BR_RIGHT_LSB
), domain
);
61 /* Clear bit 29:27 of display control register */
62 dispControl
&= ~(7 << CRT_DISPLAY_CTRL_CLK_LSB
);
63 /* Assume common fields in dispControl have been properly set before
64 calling this function.
65 This function only sets the extra fields in dispControl.
69 /* Set bit 29:27 of display control register for the right clock */
70 /* Note that SM750LE only need to supported 7 resoluitons. */
71 dispControl
&= (~(7 << CRT_DISPLAY_CTRL_CLK_LSB
));
72 if (x
== 800 && y
== 600)
73 dispControl
|= 1 << CRT_DISPLAY_CTRL_CLK_LSB
;
74 else if (x
== 1024 && y
== 768)
75 dispControl
|= 3 << CRT_DISPLAY_CTRL_CLK_LSB
;
76 else if (x
== 1152 && y
== 864)
77 dispControl
|= 5 << CRT_DISPLAY_CTRL_CLK_LSB
;
78 else if (x
== 1280 && y
== 768)
79 dispControl
|= 5 << CRT_DISPLAY_CTRL_CLK_LSB
;
80 else if (x
== 1280 && y
== 720)
81 dispControl
|= 4 << CRT_DISPLAY_CTRL_CLK_LSB
;
82 else if (x
== 1280 && y
== 960)
83 dispControl
|= 6 << CRT_DISPLAY_CTRL_CLK_LSB
;
84 else if (x
== 1280 && y
== 1024)
85 dispControl
|= 6 << CRT_DISPLAY_CTRL_CLK_LSB
;
86 else /* default to VGA clock */
87 dispControl
&= ~(7 << CRT_DISPLAY_CTRL_CLK_LSB
);
89 /* Set bit 25:24 of display controller */
90 dispControl
|= 1 << CRT_DISPLAY_CTRL_CRTSELECT_LSB
;
91 dispControl
&= ~(1 << CRT_DISPLAY_CTRL_RGBBIT_LSB
);
93 /* Set bit 14 of display controller */
94 dispControl
|= 1 << CRT_DISPLAY_CTRL_CLOCK_PHASE_LSB
;
95 POKE32(CRT_DISPLAY_CTRL
, dispControl
, domain
);
101 /* only timing related registers will be programed */
102 static int programModeRegisters(mode_parameter_t
* pModeParam
,
103 pll_value_t
* pll
, int domain
)
107 unsigned int ulTmpValue
, ulReg
;
108 if (pll
->clockType
== SECONDARY_PLL
) {
109 /* programe secondary pixel clock */
110 POKE32(CRT_PLL_CTRL
, formatPllReg(pll
), domain
);
111 POKE32(CRT_HORIZONTAL_TOTAL
,
112 ((pModeParam
->horizontal_total
-
113 1) << CRT_HORIZONTAL_TOTAL_TOTAL_LSB
)
114 | ((pModeParam
->horizontal_display_end
- 1) <<
115 CRT_HORIZONTAL_TOTAL_DISPLAY_END_LSB
), domain
);
117 POKE32(CRT_HORIZONTAL_SYNC
,
119 horizontal_sync_width
<<
120 CRT_HORIZONTAL_SYNC_WIDTH_LSB
)
121 | ((pModeParam
->horizontal_sync_start
- 1) <<
122 CRT_HORIZONTAL_SYNC_START_LSB
), domain
);
124 POKE32(CRT_VERTICAL_TOTAL
,
125 ((pModeParam
->vertical_total
-
126 1) << CRT_VERTICAL_TOTAL_TOTAL_LSB
)
127 | ((pModeParam
->vertical_display_end
- 1) <<
128 CRT_VERTICAL_TOTAL_DISPLAY_END_LSB
), domain
);
129 POKE32(CRT_VERTICAL_SYNC
,
131 vertical_sync_height
<<
132 CRT_VERTICAL_SYNC_HEIGHT_LSB
)
133 | ((pModeParam
->vertical_sync_start
- 1) <<
134 CRT_VERTICAL_SYNC_START_LSB
), domain
);
139 vertical_sync_polarity
<<
140 CRT_DISPLAY_CTRL_VSYNC_PHASE_LSB
) | (pModeParam
->
141 horizontal_sync_polarity
143 CRT_DISPLAY_CTRL_HSYNC_PHASE_LSB
)
144 | (1 << CRT_DISPLAY_CTRL_TIMING_LSB
) | (1 <<
145 CRT_DISPLAY_CTRL_PLANE_LSB
);
147 if (getChipType(domain
) == SM750LE
) {
148 displayControlAdjust_SM750LE(pModeParam
,
151 ulReg
= PEEK32(CRT_DISPLAY_CTRL
, domain
)
152 & (~(1 << CRT_DISPLAY_CTRL_VSYNC_PHASE_LSB
))
153 & (~(1 << CRT_DISPLAY_CTRL_HSYNC_PHASE_LSB
))
154 & (~(1 << CRT_DISPLAY_CTRL_TIMING_LSB
))
155 & (~(1 << CRT_DISPLAY_CTRL_PLANE_LSB
));
156 POKE32(CRT_DISPLAY_CTRL
, ulTmpValue
| ulReg
, domain
);
159 } else if (pll
->clockType
== PRIMARY_PLL
) {
160 unsigned int ulReservedBits
;
161 POKE32(PANEL_PLL_CTRL
, formatPllReg(pll
), domain
);
162 POKE32(PANEL_HORIZONTAL_TOTAL
,
163 ((pModeParam
->horizontal_total
-
164 1) << PANEL_HORIZONTAL_TOTAL_TOTAL_LSB
)
165 | ((pModeParam
->horizontal_display_end
- 1) <<
166 PANEL_HORIZONTAL_TOTAL_DISPLAY_END_LSB
), domain
);
168 POKE32(PANEL_HORIZONTAL_SYNC
,
170 horizontal_sync_width
<<
171 PANEL_HORIZONTAL_SYNC_WIDTH_LSB
)
172 | ((pModeParam
->horizontal_sync_start
- 1) <<
173 PANEL_HORIZONTAL_SYNC_START_LSB
), domain
);
175 POKE32(PANEL_VERTICAL_TOTAL
,
176 ((pModeParam
->vertical_total
- 1)
177 << PANEL_VERTICAL_TOTAL_TOTAL_LSB
)
178 | ((pModeParam
->vertical_display_end
- 1) <<
179 PANEL_VERTICAL_TOTAL_DISPLAY_END_LSB
), domain
);
181 POKE32(PANEL_VERTICAL_SYNC
,
182 (pModeParam
->vertical_sync_height
<<
183 PANEL_VERTICAL_SYNC_HEIGHT_LSB
)
184 | ((pModeParam
->vertical_sync_start
- 1) <<
185 PANEL_VERTICAL_SYNC_START_LSB
), domain
);
187 (pModeParam
->vertical_sync_polarity
<<
188 PANEL_DISPLAY_CTRL_VSYNC_PHASE_LSB
)
189 | (pModeParam
->horizontal_sync_polarity
<<
190 PANEL_DISPLAY_CTRL_HSYNC_PHASE_LSB
)
191 | (pModeParam
->clock_phase_polarity
<<
192 PANEL_DISPLAY_CTRL_CLOCK_PHASE_LSB
)
193 | (1 << PANEL_DISPLAY_CTRL_TIMING_LSB
)
194 | (1 << PANEL_DISPLAY_CTRL_PLANE_LSB
);
196 (3 << PANEL_DISPLAY_CTRL_RESERVED_1_MASK_LSB
) | (15 <<
197 PANEL_DISPLAY_CTRL_RESERVED_2_MASK_LSB
)
198 | (1 << PANEL_DISPLAY_CTRL_RESERVED_3_MASK_LSB
) | (1 <<
199 PANEL_DISPLAY_CTRL_VSYNC_LSB
);
200 ulReg
= (PEEK32(PANEL_DISPLAY_CTRL
, domain
) & ~ulReservedBits
)
201 & (~(1 << PANEL_DISPLAY_CTRL_CLOCK_PHASE_LSB
))
202 & (~(1 << PANEL_DISPLAY_CTRL_VSYNC_PHASE_LSB
))
203 & (~(1 << PANEL_DISPLAY_CTRL_HSYNC_PHASE_LSB
))
204 & (~(1 << PANEL_DISPLAY_CTRL_TIMING_LSB
))
205 & (~(1 << PANEL_DISPLAY_CTRL_PLANE_LSB
));
207 /* May a hardware bug or just my test chip (not confirmed).
208 * PANEL_DISPLAY_CTRL register seems requiring few writes
209 * before a value can be succesfully written in.
210 * Added some masks to mask out the reserved bits.
211 * Note: This problem happens by design. The hardware will wait for the
212 * next vertical sync to turn on/off the plane.
215 POKE32(PANEL_DISPLAY_CTRL
, ulTmpValue
| ulReg
, domain
);
217 while ((PEEK32(PANEL_DISPLAY_CTRL
, domain
) & ~ulReservedBits
) !=
218 (ulTmpValue
| ulReg
)) {
222 POKE32(PANEL_DISPLAY_CTRL
, ulTmpValue
| ulReg
, domain
);
231 int ddk750_setModeTiming(mode_parameter_t
* parm
, clock_type_t clock
, int domain
)
234 unsigned int uiActualPixelClk
;
235 pll
.inputFreq
= DEFAULT_INPUT_CLOCK
;
236 pll
.clockType
= clock
;
238 uiActualPixelClk
= calcPllValue(parm
->pixel_clock
, &pll
, domain
);
239 if (getChipType(domain
) == SM750LE
) {
240 /* set graphic mode via IO method */
244 programModeRegisters(parm
, &pll
, domain
);
248 #else /* !CONFIG_FB_LYNXFB_DOMAINS: */
251 This function takes care extra registers and bit fields required to set
254 Explanation about Display Control register:
255 HW only supports 7 predefined pixel clocks, and clock select is
256 in bit 29:27 of Display Control register.
258 static unsigned long displayControlAdjust_SM750LE(mode_parameter_t
*
265 x
= pModeParam
->horizontal_display_end
;
266 y
= pModeParam
->vertical_display_end
;
268 /* SM750LE has to set up the top-left and bottom-right
270 Note that normal SM750/SM718 only use those two register for
273 POKE32(CRT_AUTO_CENTERING_TL
,
274 (~(0x7FF << CRT_AUTO_CENTERING_TL_TOP_LSB
)) &
275 (~(0x7FF << CRT_AUTO_CENTERING_TL_LEFT_LSB
)));
278 POKE32(CRT_AUTO_CENTERING_BR
,
279 (~(0x7FF << CRT_AUTO_CENTERING_BR_BOTTOM_LSB
)) |
280 (~(0x7FF << CRT_AUTO_CENTERING_BR_RIGHT_LSB
)));
281 POKE32(CRT_AUTO_CENTERING_BR
,
282 ((y
- 1) << CRT_AUTO_CENTERING_BR_BOTTOM_LSB
) |
283 ((x
- 1) << CRT_AUTO_CENTERING_BR_RIGHT_LSB
));
284 /* Clear bit 29:27 of display control register */
285 dispControl
&= ~(7 << CRT_DISPLAY_CTRL_CLK_LSB
);
286 /* Assume common fields in dispControl have been properly set before
287 calling this function.
288 This function only sets the extra fields in dispControl.
292 /* Set bit 29:27 of display control register for the right clock */
293 /* Note that SM750LE only need to supported 7 resoluitons. */
294 dispControl
&= (~(7 << CRT_DISPLAY_CTRL_CLK_LSB
));
295 if (x
== 800 && y
== 600)
296 dispControl
|= 1 << CRT_DISPLAY_CTRL_CLK_LSB
;
297 else if (x
== 1024 && y
== 768)
298 dispControl
|= 3 << CRT_DISPLAY_CTRL_CLK_LSB
;
299 else if (x
== 1152 && y
== 864)
300 dispControl
|= 5 << CRT_DISPLAY_CTRL_CLK_LSB
;
301 else if (x
== 1280 && y
== 768)
302 dispControl
|= 5 << CRT_DISPLAY_CTRL_CLK_LSB
;
303 else if (x
== 1280 && y
== 720)
304 dispControl
|= 4 << CRT_DISPLAY_CTRL_CLK_LSB
;
305 else if (x
== 1280 && y
== 960)
306 dispControl
|= 6 << CRT_DISPLAY_CTRL_CLK_LSB
;
307 else if (x
== 1280 && y
== 1024)
308 dispControl
|= 6 << CRT_DISPLAY_CTRL_CLK_LSB
;
309 else /* default to VGA clock */
310 dispControl
&= ~(7 << CRT_DISPLAY_CTRL_CLK_LSB
);
312 /* Set bit 25:24 of display controller */
313 dispControl
|= 1 << CRT_DISPLAY_CTRL_CRTSELECT_LSB
;
314 dispControl
&= ~(1 << CRT_DISPLAY_CTRL_RGBBIT_LSB
);
316 /* Set bit 14 of display controller */
317 dispControl
|= 1 << CRT_DISPLAY_CTRL_CLOCK_PHASE_LSB
;
318 POKE32(CRT_DISPLAY_CTRL
, dispControl
);
326 /* only timing related registers will be programed */
327 static int programModeRegisters(mode_parameter_t
* pModeParam
,
332 unsigned int ulTmpValue
, ulReg
;
333 if (pll
->clockType
== SECONDARY_PLL
) {
334 /* programe secondary pixel clock */
335 POKE32(CRT_PLL_CTRL
, formatPllReg(pll
));
336 POKE32(CRT_HORIZONTAL_TOTAL
,
337 ((pModeParam
->horizontal_total
-
338 1) << CRT_HORIZONTAL_TOTAL_TOTAL_LSB
)
339 | ((pModeParam
->horizontal_display_end
- 1) <<
340 CRT_HORIZONTAL_TOTAL_DISPLAY_END_LSB
));
342 POKE32(CRT_HORIZONTAL_SYNC
,
344 horizontal_sync_width
<<
345 CRT_HORIZONTAL_SYNC_WIDTH_LSB
)
346 | ((pModeParam
->horizontal_sync_start
- 1) <<
347 CRT_HORIZONTAL_SYNC_START_LSB
));
349 POKE32(CRT_VERTICAL_TOTAL
,
350 ((pModeParam
->vertical_total
-
351 1) << CRT_VERTICAL_TOTAL_TOTAL_LSB
)
352 | ((pModeParam
->vertical_display_end
- 1) <<
353 CRT_VERTICAL_TOTAL_DISPLAY_END_LSB
));
354 POKE32(CRT_VERTICAL_SYNC
,
356 vertical_sync_height
<<
357 CRT_VERTICAL_SYNC_HEIGHT_LSB
)
358 | ((pModeParam
->vertical_sync_start
- 1) <<
359 CRT_VERTICAL_SYNC_START_LSB
));
364 vertical_sync_polarity
<<
365 CRT_DISPLAY_CTRL_VSYNC_PHASE_LSB
) | (pModeParam
->
366 horizontal_sync_polarity
368 CRT_DISPLAY_CTRL_HSYNC_PHASE_LSB
)
369 | (1 << CRT_DISPLAY_CTRL_TIMING_LSB
) | (1 <<
370 CRT_DISPLAY_CTRL_PLANE_LSB
);
372 if (getChipType() == SM750LE
) {
373 displayControlAdjust_SM750LE(pModeParam
,
376 ulReg
= PEEK32(CRT_DISPLAY_CTRL
)
377 & (~(1 << CRT_DISPLAY_CTRL_VSYNC_PHASE_LSB
))
378 & (~(1 << CRT_DISPLAY_CTRL_HSYNC_PHASE_LSB
))
379 & (~(1 << CRT_DISPLAY_CTRL_TIMING_LSB
))
380 & (~(1 << CRT_DISPLAY_CTRL_PLANE_LSB
));
381 POKE32(CRT_DISPLAY_CTRL
, ulTmpValue
| ulReg
);
384 } else if (pll
->clockType
== PRIMARY_PLL
) {
385 unsigned int ulReservedBits
;
386 POKE32(PANEL_PLL_CTRL
, formatPllReg(pll
));
387 POKE32(PANEL_HORIZONTAL_TOTAL
,
388 ((pModeParam
->horizontal_total
-
389 1) << PANEL_HORIZONTAL_TOTAL_TOTAL_LSB
)
390 | ((pModeParam
->horizontal_display_end
- 1) <<
391 PANEL_HORIZONTAL_TOTAL_DISPLAY_END_LSB
));
393 POKE32(PANEL_HORIZONTAL_SYNC
,
395 horizontal_sync_width
<<
396 PANEL_HORIZONTAL_SYNC_WIDTH_LSB
)
397 | ((pModeParam
->horizontal_sync_start
- 1) <<
398 PANEL_HORIZONTAL_SYNC_START_LSB
));
400 POKE32(PANEL_VERTICAL_TOTAL
,
401 ((pModeParam
->vertical_total
- 1)
402 << PANEL_VERTICAL_TOTAL_TOTAL_LSB
)
403 | ((pModeParam
->vertical_display_end
- 1) <<
404 PANEL_VERTICAL_TOTAL_DISPLAY_END_LSB
));
406 POKE32(PANEL_VERTICAL_SYNC
,
407 (pModeParam
->vertical_sync_height
<<
408 PANEL_VERTICAL_SYNC_HEIGHT_LSB
)
409 | ((pModeParam
->vertical_sync_start
- 1) <<
410 PANEL_VERTICAL_SYNC_START_LSB
));
412 (pModeParam
->vertical_sync_polarity
<<
413 PANEL_DISPLAY_CTRL_VSYNC_PHASE_LSB
)
414 | (pModeParam
->horizontal_sync_polarity
<<
415 PANEL_DISPLAY_CTRL_HSYNC_PHASE_LSB
)
416 | (pModeParam
->clock_phase_polarity
<<
417 PANEL_DISPLAY_CTRL_CLOCK_PHASE_LSB
)
418 | (1 << PANEL_DISPLAY_CTRL_TIMING_LSB
)
419 | (1 << PANEL_DISPLAY_CTRL_PLANE_LSB
);
421 (3 << PANEL_DISPLAY_CTRL_RESERVED_1_MASK_LSB
) | (15 <<
422 PANEL_DISPLAY_CTRL_RESERVED_2_MASK_LSB
)
423 | (1 << PANEL_DISPLAY_CTRL_RESERVED_3_MASK_LSB
) | (1 <<
424 PANEL_DISPLAY_CTRL_VSYNC_LSB
);
425 ulReg
= (PEEK32(PANEL_DISPLAY_CTRL
) & ~ulReservedBits
)
426 & (~(1 << PANEL_DISPLAY_CTRL_CLOCK_PHASE_LSB
))
427 & (~(1 << PANEL_DISPLAY_CTRL_VSYNC_PHASE_LSB
))
428 & (~(1 << PANEL_DISPLAY_CTRL_HSYNC_PHASE_LSB
))
429 & (~(1 << PANEL_DISPLAY_CTRL_TIMING_LSB
))
430 & (~(1 << PANEL_DISPLAY_CTRL_PLANE_LSB
));
432 /* May a hardware bug or just my test chip (not confirmed).
433 * PANEL_DISPLAY_CTRL register seems requiring few writes
434 * before a value can be succesfully written in.
435 * Added some masks to mask out the reserved bits.
436 * Note: This problem happens by design. The hardware will wait for the
437 * next vertical sync to turn on/off the plane.
440 POKE32(PANEL_DISPLAY_CTRL
, ulTmpValue
| ulReg
);
442 while ((PEEK32(PANEL_DISPLAY_CTRL
) & ~ulReservedBits
) !=
443 (ulTmpValue
| ulReg
)) {
447 POKE32(PANEL_DISPLAY_CTRL
, ulTmpValue
| ulReg
);
456 int ddk750_setModeTiming(mode_parameter_t
* parm
, clock_type_t clock
)
459 unsigned int uiActualPixelClk
;
460 pll
.inputFreq
= DEFAULT_INPUT_CLOCK
;
461 pll
.clockType
= clock
;
463 uiActualPixelClk
= calcPllValue(parm
->pixel_clock
, &pll
);
464 if (getChipType() == SM750LE
) {
465 /* set graphic mode via IO method */
469 programModeRegisters(parm
, &pll
);
472 #endif /* !CONFIG_FB_LYNXFB_DOMAINS */