Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / sm750fb / ddk750_mode.c
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 */
16 static 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 */
78 static 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
188 int 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