Merge branch 'fixes' of git://ftp.arm.linux.org.uk/~rmk/linux-arm
[linux-2.6-block.git] / drivers / staging / sm750fb / ddk750_mode.c
CommitLineData
81dee67e
SM
1
2#include "ddk750_help.h"
3#include "ddk750_reg.h"
4#include "ddk750_mode.h"
5#include "ddk750_chip.h"
6
7/*
8 SM750LE only:
9 This function takes care extra registers and bit fields required to set
10 up a mode in SM750LE
11
12 Explanation about Display Control register:
13 HW only supports 7 predefined pixel clocks, and clock select is
14 in bit 29:27 of Display Control register.
15*/
16static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, unsigned long dispControl)
17{
18 unsigned long x, y;
19
20 x = pModeParam->horizontal_display_end;
21 y = pModeParam->vertical_display_end;
22
23 /* SM750LE has to set up the top-left and bottom-right
24 registers as well.
25 Note that normal SM750/SM718 only use those two register for
26 auto-centering mode.
27 */
28 POKE32(CRT_AUTO_CENTERING_TL,
29 FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, TOP, 0)
30 | FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, LEFT, 0));
31
32 POKE32(CRT_AUTO_CENTERING_BR,
33 FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, BOTTOM, y-1)
34 | FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, RIGHT, x-1));
35
36 /* Assume common fields in dispControl have been properly set before
37 calling this function.
38 This function only sets the extra fields in dispControl.
39 */
40
41 /* Clear bit 29:27 of display control register */
42 dispControl &= FIELD_CLEAR(CRT_DISPLAY_CTRL, CLK);
43
44 /* Set bit 29:27 of display control register for the right clock */
45 /* Note that SM750LE only need to supported 7 resoluitons. */
46 if ( x == 800 && y == 600 )
47 dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL41);
48 else if (x == 1024 && y == 768)
49 dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL65);
50 else if (x == 1152 && y == 864)
51 dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
52 else if (x == 1280 && y == 768)
53 dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
54 else if (x == 1280 && y == 720)
55 dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL74);
56 else if (x == 1280 && y == 960)
57 dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
58 else if (x == 1280 && y == 1024)
59 dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
60 else /* default to VGA clock */
61 dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL25);
62
63 /* Set bit 25:24 of display controller */
64 dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CRTSELECT, CRT);
65 dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, RGBBIT, 24BIT);
66
67 /* Set bit 14 of display controller */
68 dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLOCK_PHASE, ACTIVE_LOW);
69
70 POKE32(CRT_DISPLAY_CTRL, dispControl);
71
72 return dispControl;
73}
74
75
76
77/* only timing related registers will be programed */
78static int programModeRegisters(mode_parameter_t * pModeParam,pll_value_t * pll)
79{
80 int ret = 0;
81 int cnt = 0;
82 unsigned int ulTmpValue,ulReg;
83 if(pll->clockType == SECONDARY_PLL)
84 {
85 /* programe secondary pixel clock */
86 POKE32(CRT_PLL_CTRL,formatPllReg(pll));
87 POKE32(CRT_HORIZONTAL_TOTAL,
88 FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
89 | FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));
90
91 POKE32(CRT_HORIZONTAL_SYNC,
92 FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
93 | FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));
94
95 POKE32(CRT_VERTICAL_TOTAL,
96 FIELD_VALUE(0, CRT_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
97 | FIELD_VALUE(0, CRT_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));
98
99 POKE32(CRT_VERTICAL_SYNC,
100 FIELD_VALUE(0, CRT_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
101 | FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));
102
103
104 ulTmpValue = FIELD_VALUE(0,CRT_DISPLAY_CTRL,VSYNC_PHASE,pModeParam->vertical_sync_polarity)|
105 FIELD_VALUE(0,CRT_DISPLAY_CTRL,HSYNC_PHASE,pModeParam->horizontal_sync_polarity)|
106 FIELD_SET(0,CRT_DISPLAY_CTRL,TIMING,ENABLE)|
107 FIELD_SET(0,CRT_DISPLAY_CTRL,PLANE,ENABLE);
108
109
110 if(getChipType() == SM750LE){
111 displayControlAdjust_SM750LE(pModeParam,ulTmpValue);
112 }else{
113 ulReg = PEEK32(CRT_DISPLAY_CTRL)
114 & FIELD_CLEAR(CRT_DISPLAY_CTRL,VSYNC_PHASE)
115 & FIELD_CLEAR(CRT_DISPLAY_CTRL,HSYNC_PHASE)
116 & FIELD_CLEAR(CRT_DISPLAY_CTRL,TIMING)
117 & FIELD_CLEAR(CRT_DISPLAY_CTRL,PLANE);
118
119 POKE32(CRT_DISPLAY_CTRL,ulTmpValue|ulReg);
120 }
121
122 }
123 else if(pll->clockType == PRIMARY_PLL)
124 {
125 unsigned int ulReservedBits;
126 POKE32(PANEL_PLL_CTRL,formatPllReg(pll));
127
128 POKE32(PANEL_HORIZONTAL_TOTAL,
129 FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
130 | FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));
131
132 POKE32(PANEL_HORIZONTAL_SYNC,
133 FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
134 | FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));
135
136 POKE32(PANEL_VERTICAL_TOTAL,
137 FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
138 | FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));
139
140 POKE32(PANEL_VERTICAL_SYNC,
141 FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
142 | FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));
143
144 ulTmpValue = FIELD_VALUE(0,PANEL_DISPLAY_CTRL,VSYNC_PHASE,pModeParam->vertical_sync_polarity)|
145 FIELD_VALUE(0,PANEL_DISPLAY_CTRL,HSYNC_PHASE,pModeParam->horizontal_sync_polarity)|
146 FIELD_VALUE(0,PANEL_DISPLAY_CTRL,CLOCK_PHASE,pModeParam->clock_phase_polarity)|
147 FIELD_SET(0,PANEL_DISPLAY_CTRL,TIMING,ENABLE)|
148 FIELD_SET(0,PANEL_DISPLAY_CTRL,PLANE,ENABLE);
149
150 ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
151 FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
152 FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE)|
153 FIELD_SET(0,PANEL_DISPLAY_CTRL,VSYNC,ACTIVE_LOW);
154
155 ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits)
156 & FIELD_CLEAR(PANEL_DISPLAY_CTRL, CLOCK_PHASE)
157 & FIELD_CLEAR(PANEL_DISPLAY_CTRL, VSYNC_PHASE)
158 & FIELD_CLEAR(PANEL_DISPLAY_CTRL, HSYNC_PHASE)
159 & FIELD_CLEAR(PANEL_DISPLAY_CTRL, TIMING)
160 & FIELD_CLEAR(PANEL_DISPLAY_CTRL, PLANE);
161
162
163 /* May a hardware bug or just my test chip (not confirmed).
164 * PANEL_DISPLAY_CTRL register seems requiring few writes
165 * before a value can be succesfully written in.
166 * Added some masks to mask out the reserved bits.
167 * Note: This problem happens by design. The hardware will wait for the
168 * next vertical sync to turn on/off the plane.
169 */
170
171 POKE32(PANEL_DISPLAY_CTRL,ulTmpValue|ulReg);
172#if 1
173 while((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg))
174 {
175 cnt++;
176 if(cnt > 1000)
177 break;
178 POKE32(PANEL_DISPLAY_CTRL,ulTmpValue|ulReg);
179 }
180#endif
181 }
182 else{
183 ret = -1;
184 }
185 return ret;
186}
187
188int ddk750_setModeTiming(mode_parameter_t * parm,clock_type_t clock)
189{
190 pll_value_t pll;
191 unsigned int uiActualPixelClk;
192 pll.inputFreq = DEFAULT_INPUT_CLOCK;
193 pll.clockType = clock;
194
195 uiActualPixelClk = calcPllValue(parm->pixel_clock,&pll);
196 if(getChipType() == SM750LE){
197 /* set graphic mode via IO method */
198 outb_p(0x88,0x3d4);
199 outb_p(0x06,0x3d5);
200 }
201 programModeRegisters(parm,&pll);
202 return 0;
203}
204
205