staging: sm750fb: share common bits in display control registers
[cascardo/linux.git] / drivers / staging / sm750fb / ddk750_chip.c
1 #include <linux/sizes.h>
2
3 #include "ddk750_help.h"
4 #include "ddk750_reg.h"
5 #include "ddk750_chip.h"
6 #include "ddk750_power.h"
7
8 logical_chip_type_t getChipType(void)
9 {
10         unsigned short physicalID;
11         char physicalRev;
12         logical_chip_type_t chip;
13
14         physicalID = devId750; /* either 0x718 or 0x750 */
15         physicalRev = revId750;
16
17         if (physicalID == 0x718)
18                 chip = SM718;
19         else if (physicalID == 0x750) {
20                 chip = SM750;
21                 /* SM750 and SM750LE are different in their revision ID only. */
22                 if (physicalRev == SM750LE_REVISION_ID)
23                         chip = SM750LE;
24         } else
25                 chip = SM_UNKNOWN;
26
27         return chip;
28 }
29
30 static unsigned int get_mxclk_freq(void)
31 {
32         unsigned int pll_reg;
33         unsigned int M, N, OD, POD;
34
35         if (getChipType() == SM750LE)
36                 return MHz(130);
37
38         pll_reg = PEEK32(MXCLK_PLL_CTRL);
39         M = (pll_reg & PLL_CTRL_M_MASK) >> PLL_CTRL_M_SHIFT;
40         N = (pll_reg & PLL_CTRL_N_MASK) >> PLL_CTRL_M_SHIFT;
41         OD = (pll_reg & PLL_CTRL_OD_MASK) >> PLL_CTRL_OD_SHIFT;
42         POD = (pll_reg & PLL_CTRL_POD_MASK) >> PLL_CTRL_POD_SHIFT;
43
44         return DEFAULT_INPUT_CLOCK * M / N / (1 << OD) / (1 << POD);
45 }
46
47 /*
48  * This function set up the main chip clock.
49  *
50  * Input: Frequency to be set.
51  */
52 static void setChipClock(unsigned int frequency)
53 {
54         pll_value_t pll;
55         unsigned int ulActualMxClk;
56
57         /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
58         if (getChipType() == SM750LE)
59                 return;
60
61         if (frequency) {
62                 /*
63                 * Set up PLL, a structure to hold the value to be set in clocks.
64                 */
65                 pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
66                 pll.clockType = MXCLK_PLL;
67
68                 /*
69                 * Call calcPllValue() to fill up the other fields for PLL structure.
70                 * Sometime, the chip cannot set up the exact clock required by User.
71                 * Return value from calcPllValue() gives the actual possible clock.
72                 */
73                 ulActualMxClk = calcPllValue(frequency, &pll);
74
75                 /* Master Clock Control: MXCLK_PLL */
76                 POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
77         }
78 }
79
80 static void setMemoryClock(unsigned int frequency)
81 {
82         unsigned int reg, divisor;
83
84         /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
85         if (getChipType() == SM750LE)
86                 return;
87
88         if (frequency) {
89                 /* Set the frequency to the maximum frequency that the DDR Memory can take
90                 which is 336MHz. */
91                 if (frequency > MHz(336))
92                         frequency = MHz(336);
93
94                 /* Calculate the divisor */
95                 divisor = roundedDiv(get_mxclk_freq(), frequency);
96
97                 /* Set the corresponding divisor in the register. */
98                 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK;
99                 switch (divisor) {
100                 default:
101                 case 1:
102                         reg |= CURRENT_GATE_M2XCLK_DIV_1;
103                         break;
104                 case 2:
105                         reg |= CURRENT_GATE_M2XCLK_DIV_2;
106                         break;
107                 case 3:
108                         reg |= CURRENT_GATE_M2XCLK_DIV_3;
109                         break;
110                 case 4:
111                         reg |= CURRENT_GATE_M2XCLK_DIV_4;
112                         break;
113                 }
114
115                 setCurrentGate(reg);
116         }
117 }
118
119 /*
120  * This function set up the master clock (MCLK).
121  *
122  * Input: Frequency to be set.
123  *
124  * NOTE:
125  *      The maximum frequency the engine can run is 168MHz.
126  */
127 static void setMasterClock(unsigned int frequency)
128 {
129         unsigned int reg, divisor;
130
131         /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
132         if (getChipType() == SM750LE)
133                 return;
134
135         if (frequency) {
136                 /* Set the frequency to the maximum frequency that the SM750 engine can
137                 run, which is about 190 MHz. */
138                 if (frequency > MHz(190))
139                         frequency = MHz(190);
140
141                 /* Calculate the divisor */
142                 divisor = roundedDiv(get_mxclk_freq(), frequency);
143
144                 /* Set the corresponding divisor in the register. */
145                 reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK;
146                 switch (divisor) {
147                 default:
148                 case 3:
149                         reg |= CURRENT_GATE_MCLK_DIV_3;
150                         break;
151                 case 4:
152                         reg |= CURRENT_GATE_MCLK_DIV_4;
153                         break;
154                 case 6:
155                         reg |= CURRENT_GATE_MCLK_DIV_6;
156                         break;
157                 case 8:
158                         reg |= CURRENT_GATE_MCLK_DIV_8;
159                         break;
160                 }
161
162                 setCurrentGate(reg);
163                 }
164 }
165
166 unsigned int ddk750_getVMSize(void)
167 {
168         unsigned int reg;
169         unsigned int data;
170
171         /* sm750le only use 64 mb memory*/
172         if (getChipType() == SM750LE)
173                 return SZ_64M;
174
175         /* for 750,always use power mode0*/
176         reg = PEEK32(MODE0_GATE);
177         reg |= MODE0_GATE_GPIO;
178         POKE32(MODE0_GATE, reg);
179
180         /* get frame buffer size from GPIO */
181         reg = PEEK32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK;
182         switch (reg) {
183         case MISC_CTRL_LOCALMEM_SIZE_8M:
184                 data = SZ_8M;  break; /* 8  Mega byte */
185         case MISC_CTRL_LOCALMEM_SIZE_16M:
186                 data = SZ_16M; break; /* 16 Mega byte */
187         case MISC_CTRL_LOCALMEM_SIZE_32M:
188                 data = SZ_32M; break; /* 32 Mega byte */
189         case MISC_CTRL_LOCALMEM_SIZE_64M:
190                 data = SZ_64M; break; /* 64 Mega byte */
191         default:
192                 data = 0;
193                 break;
194         }
195         return data;
196 }
197
198 int ddk750_initHw(initchip_param_t *pInitParam)
199 {
200         unsigned int reg;
201
202         if (pInitParam->powerMode != 0)
203                 pInitParam->powerMode = 0;
204         setPowerMode(pInitParam->powerMode);
205
206         /* Enable display power gate & LOCALMEM power gate*/
207         reg = PEEK32(CURRENT_GATE);
208         reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM);
209         setCurrentGate(reg);
210
211         if (getChipType() != SM750LE) {
212                 /*      set panel pll and graphic mode via mmio_88 */
213                 reg = PEEK32(VGA_CONFIGURATION);
214                 reg |= (VGA_CONFIGURATION_PLL | VGA_CONFIGURATION_MODE);
215                 POKE32(VGA_CONFIGURATION, reg);
216         } else {
217 #if defined(__i386__) || defined(__x86_64__)
218                 /* set graphic mode via IO method */
219                 outb_p(0x88, 0x3d4);
220                 outb_p(0x06, 0x3d5);
221 #endif
222         }
223
224         /* Set the Main Chip Clock */
225         setChipClock(MHz((unsigned int)pInitParam->chipClock));
226
227         /* Set up memory clock. */
228         setMemoryClock(MHz(pInitParam->memClock));
229
230         /* Set up master clock */
231         setMasterClock(MHz(pInitParam->masterClock));
232
233
234         /* Reset the memory controller. If the memory controller is not reset in SM750,
235            the system might hang when sw accesses the memory.
236            The memory should be resetted after changing the MXCLK.
237          */
238         if (pInitParam->resetMemory == 1) {
239                 reg = PEEK32(MISC_CTRL);
240                 reg &= ~MISC_CTRL_LOCALMEM_RESET;
241                 POKE32(MISC_CTRL, reg);
242
243                 reg |= MISC_CTRL_LOCALMEM_RESET;
244                 POKE32(MISC_CTRL, reg);
245         }
246
247         if (pInitParam->setAllEngOff == 1) {
248                 enable2DEngine(0);
249
250                 /* Disable Overlay, if a former application left it on */
251                 reg = PEEK32(VIDEO_DISPLAY_CTRL);
252                 reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, DISABLE);
253                 POKE32(VIDEO_DISPLAY_CTRL, reg);
254
255                 /* Disable video alpha, if a former application left it on */
256                 reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
257                 reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, DISABLE);
258                 POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg);
259
260                 /* Disable alpha plane, if a former application left it on */
261                 reg = PEEK32(ALPHA_DISPLAY_CTRL);
262                 reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, DISABLE);
263                 POKE32(ALPHA_DISPLAY_CTRL, reg);
264
265                 /* Disable DMA Channel, if a former application left it on */
266                 reg = PEEK32(DMA_ABORT_INTERRUPT);
267                 reg = FIELD_SET(reg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT);
268                 POKE32(DMA_ABORT_INTERRUPT, reg);
269
270                 /* Disable DMA Power, if a former application left it on */
271                 enableDMA(0);
272         }
273
274         /* We can add more initialization as needed. */
275
276         return 0;
277 }
278
279 /*
280         monk liu @ 4/6/2011:
281                    re-write the calculatePLL function of ddk750.
282                    the original version function does not use some mathematics tricks and shortcut
283                    when it doing the calculation of the best N,M,D combination
284                    I think this version gives a little upgrade in speed
285
286         750 pll clock formular:
287         Request Clock = (Input Clock * M )/(N * X)
288
289         Input Clock = 14318181 hz
290         X = 2 power D
291         D ={0,1,2,3,4,5,6}
292         M = {1,...,255}
293         N = {2,...,15}
294 */
295 unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
296 {
297         /* as sm750 register definition, N located in 2,15 and M located in 1,255       */
298         int N, M, X, d;
299         int mini_diff;
300         unsigned int RN, quo, rem, fl_quo;
301         unsigned int input, request;
302         unsigned int tmpClock, ret;
303         const int max_OD = 3;
304         int max_d;
305
306         if (getChipType() == SM750LE) {
307                 /* SM750LE don't have prgrammable PLL and M/N values to work on.
308                 Just return the requested clock. */
309                 return request_orig;
310         }
311
312         ret = 0;
313         mini_diff = ~0;
314         request = request_orig / 1000;
315         input = pll->inputFreq / 1000;
316
317         /* for MXCLK register , no POD provided, so need be treated differently */
318         if (pll->clockType == MXCLK_PLL)
319                 max_d = 3;
320
321         for (N = 15; N > 1; N--) {
322                 /* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */
323                 RN = N * request;
324                 quo = RN / input;
325                 rem = RN % input;/* rem always small than 14318181 */
326                 fl_quo = (rem * 10000 / input);
327
328                 for (d = max_d; d >= 0; d--) {
329                         X = (1 << d);
330                         M = quo * X;
331                         M += fl_quo * X / 10000;
332                         /* round step */
333                         M += (fl_quo * X % 10000) > 5000 ? 1 : 0;
334                         if (M < 256 && M > 0) {
335                                 unsigned int diff;
336
337                                 tmpClock = pll->inputFreq * M / N / X;
338                                 diff = absDiff(tmpClock, request_orig);
339                                 if (diff < mini_diff) {
340                                         pll->M = M;
341                                         pll->N = N;
342                                         pll->POD = 0;
343                                         if (d > max_OD)
344                                                 pll->POD = d - max_OD;
345                                         pll->OD = d - pll->POD;
346                                         mini_diff = diff;
347                                         ret = tmpClock;
348                                 }
349                         }
350                 }
351         }
352         return ret;
353 }
354
355 unsigned int formatPllReg(pll_value_t *pPLL)
356 {
357 #ifndef VALIDATION_CHIP
358         unsigned int POD = pPLL->POD;
359 #endif
360         unsigned int OD = pPLL->OD;
361         unsigned int M = pPLL->M;
362         unsigned int N = pPLL->N;
363         unsigned int reg = 0;
364
365         /*
366          * Note that all PLL's have the same format. Here, we just use
367          * Panel PLL parameter to work out the bit fields in the
368          * register. On returning a 32 bit number, the value can be
369          * applied to any PLL in the calling function.
370          */
371         reg = PLL_CTRL_POWER |
372 #ifndef VALIDATION_CHIP
373                 ((POD << PLL_CTRL_POD_SHIFT) & PLL_CTRL_POD_MASK) |
374 #endif
375                 ((OD << PLL_CTRL_OD_SHIFT) & PLL_CTRL_OD_MASK) |
376                 ((N << PLL_CTRL_N_SHIFT) & PLL_CTRL_N_MASK) |
377                 ((M << PLL_CTRL_M_SHIFT) & PLL_CTRL_M_MASK);
378
379         return reg;
380 }
381
382