Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / sm750fb / ddk750_chip.c
1 #include "ddk750_help.h"
2 #include "ddk750_reg.h"
3 #include "ddk750_chip.h"
4 #include "ddk750_power.h"
5 typedef struct _pllcalparam {
6         unsigned char power;/* d : 0~ 6*/
7         unsigned char pod;
8         unsigned char od;
9         unsigned char value;/* value of  2 power d (2^d) */
10 }
11 pllcalparam;
12
13
14 logical_chip_type_t getChipType(void)
15 {
16         unsigned short physicalID;
17         char physicalRev;
18         logical_chip_type_t chip;
19
20         physicalID = devId750;//either 0x718 or 0x750
21         physicalRev = revId750;
22
23         if (physicalID == 0x718)
24                 chip = SM718;
25         else if (physicalID == 0x750) {
26                 chip = SM750;
27                 /* SM750 and SM750LE are different in their revision ID only. */
28                 if (physicalRev == SM750LE_REVISION_ID)
29                         chip = SM750LE;
30         } else
31                 chip = SM_UNKNOWN;
32
33         return chip;
34 }
35
36
37 inline unsigned int twoToPowerOfx(unsigned long x)
38 {
39         unsigned long i;
40         unsigned long result = 1;
41
42         for (i = 1; i <= x; i++)
43                 result *= 2;
44         return result;
45 }
46
47 inline unsigned int calcPLL(pll_value_t *pPLL)
48 {
49         return (pPLL->inputFreq * pPLL->M / pPLL->N / twoToPowerOfx(pPLL->OD) / twoToPowerOfx(pPLL->POD));
50 }
51
52 unsigned int getPllValue(clock_type_t clockType, pll_value_t *pPLL)
53 {
54         unsigned int ulPllReg = 0;
55
56         pPLL->inputFreq = DEFAULT_INPUT_CLOCK;
57         pPLL->clockType = clockType;
58
59         switch (clockType) {
60         case MXCLK_PLL:
61                 ulPllReg = PEEK32(MXCLK_PLL_CTRL);
62                 break;
63         case PRIMARY_PLL:
64                 ulPllReg = PEEK32(PANEL_PLL_CTRL);
65                 break;
66         case SECONDARY_PLL:
67                 ulPllReg = PEEK32(CRT_PLL_CTRL);
68                 break;
69         case VGA0_PLL:
70                 ulPllReg = PEEK32(VGA_PLL0_CTRL);
71                 break;
72         case VGA1_PLL:
73                 ulPllReg = PEEK32(VGA_PLL1_CTRL);
74                 break;
75         }
76
77         pPLL->M = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, M);
78         pPLL->N = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, N);
79         pPLL->OD = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, OD);
80         pPLL->POD = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, POD);
81
82         return calcPLL(pPLL);
83 }
84
85
86 unsigned int getChipClock(void)
87 {
88         pll_value_t pll;
89 #if 1
90         if (getChipType() == SM750LE)
91                 return MHz(130);
92 #endif
93
94         return getPllValue(MXCLK_PLL, &pll);
95 }
96
97
98 /*
99  * This function set up the main chip clock.
100  *
101  * Input: Frequency to be set.
102  */
103 void setChipClock(unsigned int frequency)
104 {
105         pll_value_t pll;
106         unsigned int ulActualMxClk;
107 #if 1
108         /* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */
109         if (getChipType() == SM750LE)
110                 return;
111 #endif
112
113         if (frequency) {
114                 /*
115                 * Set up PLL, a structure to hold the value to be set in clocks.
116                 */
117                 pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */
118                 pll.clockType = MXCLK_PLL;
119
120                 /*
121                 * Call calcPllValue() to fill up the other fields for PLL structure.
122                 * Sometime, the chip cannot set up the exact clock required by User.
123                 * Return value from calcPllValue() gives the actual possible clock.
124                 */
125                 ulActualMxClk = calcPllValue(frequency, &pll);
126
127                 /* Master Clock Control: MXCLK_PLL */
128                 POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll));
129         }
130 }
131
132
133
134 void setMemoryClock(unsigned int frequency)
135 {
136         unsigned int ulReg, divisor;
137  #if 1
138         /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
139         if (getChipType() == SM750LE)
140                 return;
141 #endif
142         if (frequency) {
143                 /* Set the frequency to the maximum frequency that the DDR Memory can take
144                 which is 336MHz. */
145                 if (frequency > MHz(336))
146                         frequency = MHz(336);
147
148                 /* Calculate the divisor */
149                 divisor = (unsigned int) roundedDiv(getChipClock(), frequency);
150
151                 /* Set the corresponding divisor in the register. */
152                 ulReg = PEEK32(CURRENT_GATE);
153                 switch (divisor) {
154                 default:
155                 case 1:
156                         ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_1);
157                         break;
158                 case 2:
159                         ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_2);
160                         break;
161                 case 3:
162                         ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_3);
163                         break;
164                 case 4:
165                         ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_4);
166                         break;
167                 }
168
169                 setCurrentGate(ulReg);
170         }
171 }
172
173
174 /*
175  * This function set up the master clock (MCLK).
176  *
177  * Input: Frequency to be set.
178  *
179  * NOTE:
180  *      The maximum frequency the engine can run is 168MHz.
181  */
182 void setMasterClock(unsigned int frequency)
183 {
184         unsigned int ulReg, divisor;
185 #if 1
186         /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
187         if (getChipType() == SM750LE)
188                 return;
189 #endif
190         if (frequency) {
191                 /* Set the frequency to the maximum frequency that the SM750 engine can
192                 run, which is about 190 MHz. */
193                 if (frequency > MHz(190))
194                         frequency = MHz(190);
195
196                 /* Calculate the divisor */
197                 divisor = (unsigned int) roundedDiv(getChipClock(), frequency);
198
199                 /* Set the corresponding divisor in the register. */
200                 ulReg = PEEK32(CURRENT_GATE);
201                 switch (divisor) {
202                 default:
203                 case 3:
204                         ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_3);
205                         break;
206                 case 4:
207                         ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_4);
208                         break;
209                 case 6:
210                         ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_6);
211                         break;
212                 case 8:
213                         ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_8);
214                         break;
215                 }
216
217                 setCurrentGate(ulReg);
218                 }
219 }
220
221
222 unsigned int ddk750_getVMSize(void)
223 {
224         unsigned int reg;
225         unsigned int data;
226
227         /* sm750le only use 64 mb memory*/
228         if (getChipType() == SM750LE)
229                 return MB(64);
230
231         /* for 750,always use power mode0*/
232         reg = PEEK32(MODE0_GATE);
233         reg = FIELD_SET(reg, MODE0_GATE, GPIO, ON);
234         POKE32(MODE0_GATE, reg);
235
236         /* get frame buffer size from GPIO */
237         reg = FIELD_GET(PEEK32(MISC_CTRL), MISC_CTRL, LOCALMEM_SIZE);
238         switch (reg) {
239         case MISC_CTRL_LOCALMEM_SIZE_8M:
240                 data = MB(8);  break; /* 8  Mega byte */
241         case MISC_CTRL_LOCALMEM_SIZE_16M:
242                 data = MB(16); break; /* 16 Mega byte */
243         case MISC_CTRL_LOCALMEM_SIZE_32M:
244                 data = MB(32); break; /* 32 Mega byte */
245         case MISC_CTRL_LOCALMEM_SIZE_64M:
246                 data = MB(64); break; /* 64 Mega byte */
247         default:
248                 data = 0;
249                 break;
250         }
251         return data;
252
253 }
254
255 int ddk750_initHw(initchip_param_t *pInitParam)
256 {
257
258         unsigned int ulReg;
259 #if 0
260         //move the code to map regiter function.
261         if (getChipType() == SM718) {
262                 /* turn on big endian bit*/
263                 ulReg = PEEK32(0x74);
264                 /* now consider register definition in a big endian pattern*/
265                 POKE32(0x74, ulReg|0x80000000);
266         }
267
268 #endif
269
270
271         if (pInitParam->powerMode != 0 )
272                 pInitParam->powerMode = 0;
273         setPowerMode(pInitParam->powerMode);
274
275         /* Enable display power gate & LOCALMEM power gate*/
276         ulReg = PEEK32(CURRENT_GATE);
277         ulReg = FIELD_SET(ulReg, CURRENT_GATE, DISPLAY, ON);
278         ulReg = FIELD_SET(ulReg, CURRENT_GATE, LOCALMEM, ON);
279         setCurrentGate(ulReg);
280
281         if (getChipType() != SM750LE) {
282                 /*      set panel pll and graphic mode via mmio_88 */
283                 ulReg = PEEK32(VGA_CONFIGURATION);
284                 ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, PLL, PANEL);
285                 ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, MODE, GRAPHIC);
286                 POKE32(VGA_CONFIGURATION, ulReg);
287         } else {
288 #if defined(__i386__) || defined( __x86_64__)
289                 /* set graphic mode via IO method */
290                 outb_p(0x88, 0x3d4);
291                 outb_p(0x06, 0x3d5);
292 #endif
293         }
294
295         /* Set the Main Chip Clock */
296         setChipClock(MHz((unsigned int)pInitParam->chipClock));
297
298         /* Set up memory clock. */
299         setMemoryClock(MHz(pInitParam->memClock));
300
301         /* Set up master clock */
302         setMasterClock(MHz(pInitParam->masterClock));
303
304
305         /* Reset the memory controller. If the memory controller is not reset in SM750,
306            the system might hang when sw accesses the memory.
307            The memory should be resetted after changing the MXCLK.
308          */
309         if (pInitParam->resetMemory == 1) {
310                 ulReg = PEEK32(MISC_CTRL);
311                 ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, RESET);
312                 POKE32(MISC_CTRL, ulReg);
313
314                 ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, NORMAL);
315                 POKE32(MISC_CTRL, ulReg);
316         }
317
318         if (pInitParam->setAllEngOff == 1) {
319                 enable2DEngine(0);
320
321                 /* Disable Overlay, if a former application left it on */
322                 ulReg = PEEK32(VIDEO_DISPLAY_CTRL);
323                 ulReg = FIELD_SET(ulReg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE);
324                 POKE32(VIDEO_DISPLAY_CTRL, ulReg);
325
326                 /* Disable video alpha, if a former application left it on */
327                 ulReg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
328                 ulReg = FIELD_SET(ulReg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
329                 POKE32(VIDEO_ALPHA_DISPLAY_CTRL, ulReg);
330
331                 /* Disable alpha plane, if a former application left it on */
332                 ulReg = PEEK32(ALPHA_DISPLAY_CTRL);
333                 ulReg = FIELD_SET(ulReg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
334                 POKE32(ALPHA_DISPLAY_CTRL, ulReg);
335
336 #if 0
337                 /* Disable LCD hardware cursor, if a former application left it on */
338                 ulReg = PEEK32(PANEL_HWC_ADDRESS);
339                 ulReg = FIELD_SET(ulReg, PANEL_HWC_ADDRESS, ENABLE, DISABLE);
340                 POKE32(PANEL_HWC_ADDRESS, ulReg);
341
342                 /* Disable CRT hardware cursor, if a former application left it on */
343                 ulReg = PEEK32(CRT_HWC_ADDRESS);
344                 ulReg = FIELD_SET(ulReg, CRT_HWC_ADDRESS, ENABLE, DISABLE);
345                 POKE32(CRT_HWC_ADDRESS, ulReg);
346
347                 /* Disable ZV Port 0, if a former application left it on */
348                 ulReg = PEEK32(ZV0_CAPTURE_CTRL);
349                 ulReg = FIELD_SET(ulReg, ZV0_CAPTURE_CTRL, CAP, DISABLE);
350                 POKE32(ZV0_CAPTURE_CTRL, ulReg);
351
352                 /* Disable ZV Port 1, if a former application left it on */
353                 ulReg = PEEK32(ZV1_CAPTURE_CTRL);
354                 ulReg = FIELD_SET(ulReg, ZV1_CAPTURE_CTRL, CAP, DISABLE);
355                 POKE32(ZV1_CAPTURE_CTRL, ulReg);
356
357                 /* Disable ZV Port Power, if a former application left it on */
358                 enableZVPort(0);
359                 /* Disable DMA Channel, if a former application left it on */
360                 ulReg = PEEK32(DMA_ABORT_INTERRUPT);
361                 ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT);
362                 POKE32(DMA_ABORT_INTERRUPT, ulReg);
363
364                 /* Disable i2c */
365                 enableI2C(0);
366 #endif
367                 /* Disable DMA Channel, if a former application left it on */
368                 ulReg = PEEK32(DMA_ABORT_INTERRUPT);
369                 ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT);
370                 POKE32(DMA_ABORT_INTERRUPT, ulReg);
371
372                 /* Disable DMA Power, if a former application left it on */
373                 enableDMA(0);
374         }
375
376         /* We can add more initialization as needed. */
377
378         return 0;
379 }
380
381 #if 0
382
383 unsigned int absDiff(unsigned int a, unsigned int b)
384 {
385         if ( a > b )
386                 return(a - b);
387         else
388                 return(b - a);
389 }
390
391 #endif
392 /*
393         monk liu @ 4/6/2011:
394                    re-write the calculatePLL function of ddk750.
395                    the original version function does not use some mathematics tricks and shortcut
396                    when it doing the calculation of the best N,M,D combination
397                    I think this version gives a little upgrade in speed
398
399         750 pll clock formular:
400         Request Clock = (Input Clock * M )/(N * X)
401
402         Input Clock = 14318181 hz
403         X = 2 power D
404         D ={0,1,2,3,4,5,6}
405         M = {1,...,255}
406         N = {2,...,15}
407 */
408 unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll)
409 {
410         /* used for primary and secondary channel pixel clock pll */
411         static pllcalparam xparm_PIXEL[] = {
412                 /* 2^0 = 1*/                    {0, 0, 0, 1},
413                 /* 2^ 1 =2*/                    {1, 0, 1, 2},
414                 /* 2^ 2  = 4*/          {2, 0, 2, 4},
415                                                         {3, 0, 3, 8},
416                                                         {4, 1, 3, 16},
417                                                         {5, 2, 3, 32},
418                 /* 2^6 = 64  */         {6, 3, 3, 64},
419                                                         };
420
421         /* used for MXCLK (chip clock) */
422         static pllcalparam xparm_MXCLK[] = {
423                 /* 2^0 = 1*/                    {0, 0, 0, 1},
424                 /* 2^ 1 =2*/                    {1, 0, 1, 2},
425                 /* 2^ 2  = 4*/          {2, 0, 2, 4},
426                                                         {3, 0, 3, 8},
427                                                         };
428
429         /* as sm750 register definition, N located in 2,15 and M located in 1,255       */
430         int N, M, X, d;
431         int xcnt;
432         int miniDiff;
433         unsigned int RN, quo, rem, fl_quo;
434         unsigned int input, request;
435         unsigned int tmpClock, ret;
436         pllcalparam * xparm;
437
438 #if 1
439         if (getChipType() == SM750LE) {
440                 /* SM750LE don't have prgrammable PLL and M/N values to work on.
441                 Just return the requested clock. */
442                 return request_orig;
443         }
444 #endif
445
446         ret = 0;
447         miniDiff = ~0;
448         request = request_orig / 1000;
449         input = pll->inputFreq / 1000;
450
451         /* for MXCLK register , no POD provided, so need be treated differently */
452
453         if (pll->clockType != MXCLK_PLL) {
454                 xparm = &xparm_PIXEL[0];
455                 xcnt = sizeof(xparm_PIXEL)/sizeof(xparm_PIXEL[0]);
456         } else {
457                 xparm = &xparm_MXCLK[0];
458                 xcnt = sizeof(xparm_MXCLK)/sizeof(xparm_MXCLK[0]);
459         }
460
461
462         for (N = 15; N > 1; N--) {
463                 /* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */
464                 RN = N * request;
465                 quo = RN / input;
466                 rem = RN % input;/* rem always small than 14318181 */
467                 fl_quo = (rem * 10000 /input);
468
469                 for (d = xcnt - 1; d >= 0; d--) {
470                         X = xparm[d].value;
471                         M = quo*X;
472                         M += fl_quo * X / 10000;
473                         /* round step */
474                         M += (fl_quo*X % 10000)>5000?1:0;
475                         if (M < 256 && M > 0) {
476                                 unsigned int diff;
477                                 tmpClock = pll->inputFreq *M / N / X;
478                                 diff = absDiff(tmpClock, request_orig);
479                                 if (diff < miniDiff) {
480                                         pll->M = M;
481                                         pll->N = N;
482                                         pll->OD = xparm[d].od;
483                                         pll->POD = xparm[d].pod;
484                                         miniDiff = diff;
485                                         ret = tmpClock;
486                                 }
487                         }
488                 }
489         }
490
491         //printk("Finally:  pll->n[%lu],m[%lu],od[%lu],pod[%lu]\n",pll->N,pll->M,pll->OD,pll->POD);
492         return ret;
493 }
494
495 unsigned int calcPllValue2(
496 unsigned int ulRequestClk, /* Required pixel clock in Hz unit */
497 pll_value_t *pPLL           /* Structure to hold the value to be set in PLL */
498 )
499 {
500         unsigned int M, N, OD, POD = 0, diff, pllClk, odPower, podPower;
501         unsigned int bestDiff = 0xffffffff; /* biggest 32 bit unsigned number */
502         unsigned int ret;
503     /* Init PLL structure to know states */
504         pPLL->M = 0;
505         pPLL->N = 0;
506         pPLL->OD = 0;
507         pPLL->POD = 0;
508
509     /* Sanity check: None at the moment */
510
511     /* Convert everything in Khz range in order to avoid calculation overflow */
512         pPLL->inputFreq /= 1000;
513         ulRequestClk /= 1000;
514
515 #ifndef VALIDATION_CHIP
516     /* The maximum of post divider is 8. */
517         for (POD = 0; POD <= 3; POD++)
518 #endif
519                 {
520
521 #ifndef VALIDATION_CHIP
522         /* MXCLK_PLL does not have post divider. */
523         if ((POD > 0) && (pPLL->clockType == MXCLK_PLL))
524                 break;
525 #endif
526
527         /* Work out 2 to the power of POD */
528         podPower = twoToPowerOfx(POD);
529
530         /* OD has only 2 bits [15:14] and its value must between 0 to 3 */
531         for (OD = 0; OD <= 3; OD++) {
532                 /* Work out 2 to the power of OD */
533                 odPower = twoToPowerOfx(OD);
534
535 #ifdef VALIDATION_CHIP
536         if (odPower > 4)
537                 podPower = 4;
538         else
539                 podPower = odPower;
540 #endif
541
542                 /* N has 4 bits [11:8] and its value must between 2 and 15.
543                 The N == 1 will behave differently --> Result is not correct. */
544         for (N = 2; N <= 15; N++) {
545                 /* The formula for PLL is ulRequestClk = inputFreq * M / N / (2^OD)
546                 In the following steps, we try to work out a best M value given the others are known.
547                 To avoid decimal calculation, we use 1000 as multiplier for up to 3 decimal places of accuracy.
548                 */
549                 M = ulRequestClk * N * odPower * 1000 / pPLL->inputFreq;
550                 M = roundedDiv(M, 1000);
551
552                 /* M field has only 8 bits, reject value bigger than 8 bits */
553                 if (M < 256) {
554                         /* Calculate the actual clock for a given M & N */
555                         pllClk = pPLL->inputFreq * M / N / odPower / podPower;
556
557                         /* How much are we different from the requirement */
558                         diff = absDiff(pllClk, ulRequestClk);
559
560                         if (diff < bestDiff) {
561                                 bestDiff = diff;
562
563                                 /* Store M and N values */
564                                 pPLL->M  = M;
565                                 pPLL->N  = N;
566                                 pPLL->OD = OD;
567
568 #ifdef VALIDATION_CHIP
569                         if (OD > 2)
570                                 POD = 2;
571                         else
572                                 POD = OD;
573 #endif
574
575                         pPLL->POD = POD;
576                         }
577                 }
578         }
579         }
580         }
581
582     /* Restore input frequency from Khz to hz unit */
583 //    pPLL->inputFreq *= 1000;
584         ulRequestClk *= 1000;
585         pPLL->inputFreq = DEFAULT_INPUT_CLOCK; /* Default reference clock */
586
587     /* Output debug information */
588         //DDKDEBUGPRINT((DISPLAY_LEVEL, "calcPllValue: Requested Frequency = %d\n", ulRequestClk));
589         //DDKDEBUGPRINT((DISPLAY_LEVEL, "calcPllValue: Input CLK = %dHz, M=%d, N=%d, OD=%d, POD=%d\n", pPLL->inputFreq, pPLL->M, pPLL->N, pPLL->OD, pPLL->POD));
590
591     /* Return actual frequency that the PLL can set */
592         ret = calcPLL(pPLL);
593         return ret;
594 }
595
596
597
598
599
600 unsigned int formatPllReg(pll_value_t *pPLL)
601 {
602         unsigned int ulPllReg = 0;
603
604     /* Note that all PLL's have the same format. Here, we just use Panel PLL parameter
605        to work out the bit fields in the register.
606        On returning a 32 bit number, the value can be applied to any PLL in the calling function.
607     */
608         ulPllReg =
609         FIELD_SET(  0, PANEL_PLL_CTRL, BYPASS, OFF)
610         | FIELD_SET(  0, PANEL_PLL_CTRL, POWER,  ON)
611         | FIELD_SET(  0, PANEL_PLL_CTRL, INPUT,  OSC)
612 #ifndef VALIDATION_CHIP
613         | FIELD_VALUE(0, PANEL_PLL_CTRL, POD,    pPLL->POD)
614 #endif
615         | FIELD_VALUE(0, PANEL_PLL_CTRL, OD,     pPLL->OD)
616         | FIELD_VALUE(0, PANEL_PLL_CTRL, N,      pPLL->N)
617         | FIELD_VALUE(0, PANEL_PLL_CTRL, M,      pPLL->M);
618
619     return ulPllReg;
620 }
621
622