1#include "ddk750_help.h"
2#include "ddk750_reg.h"
3#include "ddk750_chip.h"
4#include "ddk750_power.h"
5typedef 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}
11pllcalparam;
12
13
14logical_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
37inline 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
47inline unsigned int calcPLL(pll_value_t *pPLL)
48{
49	return (pPLL->inputFreq * pPLL->M / pPLL->N / twoToPowerOfx(pPLL->OD) / twoToPowerOfx(pPLL->POD));
50}
51
52unsigned 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
86unsigned 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 */
103void 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
134void 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 */
182void 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
222unsigned 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
255int 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
383unsigned 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*/
408unsigned 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
495unsigned int calcPllValue2(
496unsigned int ulRequestClk, /* Required pixel clock in Hz unit */
497pll_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
600unsigned 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
623