staging: wilc1000: remove unnecessary inner braces
[deliverable/linux.git] / 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
478 tmpClock = pll->inputFreq * M / N / X;
479 diff = absDiff(tmpClock, request_orig);
480 if (diff < miniDiff) {
481 pll->M = M;
482 pll->N = N;
483 pll->OD = xparm[d].od;
484 pll->POD = xparm[d].pod;
485 miniDiff = diff;
486 ret = tmpClock;
487 }
488 }
489 }
490 }
491 return ret;
492 }
493
494 unsigned int calcPllValue2(
495 unsigned int ulRequestClk, /* Required pixel clock in Hz unit */
496 pll_value_t *pPLL /* Structure to hold the value to be set in PLL */
497 )
498 {
499 unsigned int M, N, OD, POD = 0, diff, pllClk, odPower, podPower;
500 unsigned int bestDiff = 0xffffffff; /* biggest 32 bit unsigned number */
501 unsigned int ret;
502 /* Init PLL structure to know states */
503 pPLL->M = 0;
504 pPLL->N = 0;
505 pPLL->OD = 0;
506 pPLL->POD = 0;
507
508 /* Sanity check: None at the moment */
509
510 /* Convert everything in Khz range in order to avoid calculation overflow */
511 pPLL->inputFreq /= 1000;
512 ulRequestClk /= 1000;
513
514 #ifndef VALIDATION_CHIP
515 /* The maximum of post divider is 8. */
516 for (POD = 0; POD <= 3; POD++)
517 #endif
518 {
519
520 #ifndef VALIDATION_CHIP
521 /* MXCLK_PLL does not have post divider. */
522 if ((POD > 0) && (pPLL->clockType == MXCLK_PLL))
523 break;
524 #endif
525
526 /* Work out 2 to the power of POD */
527 podPower = twoToPowerOfx(POD);
528
529 /* OD has only 2 bits [15:14] and its value must between 0 to 3 */
530 for (OD = 0; OD <= 3; OD++) {
531 /* Work out 2 to the power of OD */
532 odPower = twoToPowerOfx(OD);
533
534 #ifdef VALIDATION_CHIP
535 if (odPower > 4)
536 podPower = 4;
537 else
538 podPower = odPower;
539 #endif
540
541 /* N has 4 bits [11:8] and its value must between 2 and 15.
542 The N == 1 will behave differently --> Result is not correct. */
543 for (N = 2; N <= 15; N++) {
544 /* The formula for PLL is ulRequestClk = inputFreq * M / N / (2^OD)
545 In the following steps, we try to work out a best M value given the others are known.
546 To avoid decimal calculation, we use 1000 as multiplier for up to 3 decimal places of accuracy.
547 */
548 M = ulRequestClk * N * odPower * 1000 / pPLL->inputFreq;
549 M = roundedDiv(M, 1000);
550
551 /* M field has only 8 bits, reject value bigger than 8 bits */
552 if (M < 256) {
553 /* Calculate the actual clock for a given M & N */
554 pllClk = pPLL->inputFreq * M / N / odPower / podPower;
555
556 /* How much are we different from the requirement */
557 diff = absDiff(pllClk, ulRequestClk);
558
559 if (diff < bestDiff) {
560 bestDiff = diff;
561
562 /* Store M and N values */
563 pPLL->M = M;
564 pPLL->N = N;
565 pPLL->OD = OD;
566
567 #ifdef VALIDATION_CHIP
568 if (OD > 2)
569 POD = 2;
570 else
571 POD = OD;
572 #endif
573
574 pPLL->POD = POD;
575 }
576 }
577 }
578 }
579 }
580
581 /* Restore input frequency from Khz to hz unit */
582 ulRequestClk *= 1000;
583 pPLL->inputFreq = DEFAULT_INPUT_CLOCK; /* Default reference clock */
584
585 /* Return actual frequency that the PLL can set */
586 ret = calcPLL(pPLL);
587 return ret;
588 }
589
590
591
592
593
594 unsigned int formatPllReg(pll_value_t *pPLL)
595 {
596 unsigned int ulPllReg = 0;
597
598 /* Note that all PLL's have the same format. Here, we just use Panel PLL parameter
599 to work out the bit fields in the register.
600 On returning a 32 bit number, the value can be applied to any PLL in the calling function.
601 */
602 ulPllReg =
603 FIELD_SET(0, PANEL_PLL_CTRL, BYPASS, OFF)
604 | FIELD_SET(0, PANEL_PLL_CTRL, POWER, ON)
605 | FIELD_SET(0, PANEL_PLL_CTRL, INPUT, OSC)
606 #ifndef VALIDATION_CHIP
607 | FIELD_VALUE(0, PANEL_PLL_CTRL, POD, pPLL->POD)
608 #endif
609 | FIELD_VALUE(0, PANEL_PLL_CTRL, OD, pPLL->OD)
610 | FIELD_VALUE(0, PANEL_PLL_CTRL, N, pPLL->N)
611 | FIELD_VALUE(0, PANEL_PLL_CTRL, M, pPLL->M);
612
613 return ulPllReg;
614 }
615
616
This page took 0.044311 seconds and 5 git commands to generate.