Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1538 lines
41 KiB

  1. /* ======================================================================= */
  2. /*
  3. /* Filename : CLOCK.C
  4. /* Creation : Dominique Leblanc 92/10/26
  5. /*
  6. /*
  7. /* This file contains the different routines to program the ICD2061
  8. /* oscillator for the MGA family.
  9. /*
  10. /* Modifications List:
  11. /* D.L. 92/11/30: modification for a limited condition of
  12. /* searching for an exact frequency.
  13. /*
  14. /* Bart Simpson: Adaptation for CADDI
  15. /*
  16. /* ======================================================================= */
  17. #include "switches.h"
  18. #include "g3dstd.h"
  19. #include "caddi.h"
  20. #include "def.h"
  21. #include "mga.h"
  22. #include "global.h"
  23. #include "proto.h"
  24. #include "mgai_c.h"
  25. #include "mgai.h"
  26. #ifdef WINDOWS_NT
  27. #if defined(ALLOC_PRAGMA)
  28. #pragma alloc_text(PAGE,setFrequence)
  29. #pragma alloc_text(PAGE,programme_clock)
  30. #pragma alloc_text(PAGE,dummyCallDelai)
  31. #pragma alloc_text(PAGE,programme_reg_icd)
  32. #pragma alloc_text(PAGE,send_unlock)
  33. #pragma alloc_text(PAGE,send_data)
  34. #pragma alloc_text(PAGE,send_full_clock)
  35. #pragma alloc_text(PAGE,send_start)
  36. #pragma alloc_text(PAGE,send_0)
  37. #pragma alloc_text(PAGE,send_1)
  38. #pragma alloc_text(PAGE,send_stop)
  39. #pragma alloc_text(PAGE,setTVP3026Freq)
  40. #endif
  41. #if defined(ALLOC_PRAGMA)
  42. #pragma data_seg("PAGE")
  43. #endif
  44. #include "video.h"
  45. #endif /* #ifdef WINDOWS_NT */
  46. static volatile BYTE _Far * pDevice;
  47. typedef unsigned char byte;
  48. typedef unsigned short word;
  49. typedef unsigned long dword;
  50. /* this keep mclk f(vco) value to use with jitter VCLK=MCLK output value. */
  51. /* updated by function <ProgrammeClock> in module mtxinit.c */
  52. extern void delay_us(dword delai);
  53. extern long presentMclk[]; /* MCLK currently in use (module mtxinit.c) */
  54. extern byte iBoard; /* index of current selected board (module mtxinit.c)*/
  55. typedef struct
  56. {
  57. short p;
  58. short q;
  59. short m;
  60. short i;
  61. long trueFout;
  62. long fvco; /* for jitter problem, keep osc. value */
  63. long ppmError;
  64. } ST_RESULTAT;
  65. static ST_RESULTAT result;
  66. static byte init_misc;
  67. typedef union
  68. {
  69. byte var8;
  70. byte byte;
  71. byte octet;
  72. struct
  73. {
  74. byte enable_color : 1; /* 1=COLOR:0x3D?, 0=MONO:0x3B? */
  75. byte enable_RAM : 1;
  76. byte cs0 : 1;
  77. byte cs1 : 1;
  78. byte reserved : 1;
  79. byte page_select : 1;
  80. byte h_pol : 1;
  81. byte v_pol : 1;
  82. } bit;
  83. struct
  84. {
  85. byte unused : 2;
  86. byte pgmclk : 1;
  87. byte pgmdata : 1;
  88. byte reserved : 4;
  89. } clock_bit;
  90. struct
  91. {
  92. byte unused : 2;
  93. byte select : 2;
  94. byte reserved : 4;
  95. } sel_reg_output;
  96. } ST_MISC_OUTPUT;
  97. #define MISC_OUTPUT_WRITE 0x03C2
  98. #define MISC_OUTPUT_READ 0x03CC
  99. #define NBRE_M_POSSIBLE 7
  100. static ST_MISC_OUTPUT misc;
  101. typedef union
  102. {
  103. dword var32;
  104. dword dmot;
  105. dword ulong;
  106. struct
  107. {
  108. dword q_prime : 7;
  109. dword m_diviseur : 3;
  110. dword p_prime : 7;
  111. dword index_field : 4;
  112. dword unused : 11;
  113. } bit;
  114. } ST_REG_PROGRAM_DATA;
  115. ST_REG_PROGRAM_DATA reg_clock[4] = { { 0x5A8BCL }, /* REG0 video 1 */
  116. { 0x960ACL }, /* REG1 video 2 */
  117. { 0x960ACL }, /* REG2 video 3 */
  118. { 0xD44A3L }, /* MREG memory */
  119. };
  120. static long diviseur_m [ NBRE_M_POSSIBLE ] =
  121. {
  122. 1, /* 0 */
  123. 2, /* 1 */
  124. 4, /* 2 */
  125. 8, /* 3 */
  126. 16, /* 4 */
  127. 32, /* 5 */
  128. 64, /* 6 */
  129. /* 64, /* 7 */ /* we don't use this case in our calculations */
  130. };
  131. /* static long limites_i [ NBRE_I_POSSIBLE ] = old see below */
  132. static long limites_i [] =
  133. {/* min, max, I */
  134. 50000L, /* 47500000 0 */
  135. 51000L, /* 47500000 1 */
  136. 53200L, /* 52200000 2 */
  137. 58500L, /* 56300000 3 */
  138. 60700L, /* 61900000 4 */
  139. 64400L, /* 65000000 5 */
  140. 66800L, /* 68100000 6 */
  141. 73500L, /* 82300000 7 */
  142. 75600L, /* 86000000 8 */
  143. 80900L, /* 88000000 9 */
  144. 83200L, /* 90500000 10 */
  145. 91500L, /* 95000000 11 */
  146. 100000L, /* 1.0E+08 12 */
  147. 120000L, /* 1.2E+08 13 */
  148. /* 120000000L, /* 14 */
  149. };
  150. #define NBRE_I_POSSIBLE ( (sizeof(limites_i)) / (sizeof(long)) )
  151. /* old frequency & keep default value (power up)
  152. * there is output frequency value f(o)
  153. */
  154. long old_fr_reg[4] = { { 25175L }, /* REG0 video 1 */
  155. { 28322L }, /* REG1 video 2 */
  156. { 28322L }, /* REG2 video 3 */
  157. { 32500L }, /* MREG memory */
  158. };
  159. /**************** LIST OF REGISTERS OF ICD2061 ************************/
  160. #define NBRE_REG_ICD2061 6
  161. #define VIDEO_CLOCK_1 0
  162. #define VIDEO_CLOCK_2 1
  163. #define VIDEO_CLOCK_3 2
  164. #define MEMORY_CLOCK 3
  165. #define POWERDWN_REG 4
  166. #define CONTROL_ICD2061 6
  167. static long fref;
  168. /**************************** list of routines in this file *************/
  169. dword programme_clock ( short reg, short p, short q, short m, short i );
  170. void programme_reg_icd ( volatile BYTE _Far * pDeviceParam, short reg, dword data );
  171. static void send_unlock ( void );
  172. static void send_data ( short reg, dword data );
  173. static void send_full_clock ( void );
  174. static void send_start ( void );
  175. static void send_0 ( void );
  176. static void send_1 ( void );
  177. static void send_stop ( void );
  178. static byte selectIcdOutputReg ( long reg );
  179. static void LowerVCO(long Fout, byte pll, byte pwidth, dword fvcomax, byte dac_rev1);
  180. /*** Temporary delay to be put after each acces to programable register ***/
  181. void dummyCallDelai()
  182. {
  183. byte TmpByte;
  184. mgaReadBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), TmpByte);
  185. }
  186. /***************************************************************************/
  187. /*/ setFrequence ( volatile BYTE _Far *pDeviceParam, long fout, long reg )
  188. *
  189. * For a given frequency, determines the best values to put for the
  190. * programming of the ICD2061.
  191. * Programs the register.
  192. * If outgoing frequency is 0, this function only chooses the output register.
  193. *
  194. * Problemes :
  195. * Concu : Dominique Leblanc:92/10/29
  196. *
  197. * Parametres: [0]-frequency output.
  198. * [1]-register (0, 1, 2 ou 3) which will be used
  199. * (the register 3 MCLK cannot be used as output
  200. *
  201. * Returns : programmed frequency (or 0)
  202. *
  203. */
  204. long setFrequence ( volatile BYTE _Far *pDeviceParam, long fout, long reg )
  205. {
  206. short i;
  207. long p, q, m;
  208. short index;
  209. short i_find;
  210. long old_frequency;
  211. long fvco, trueFout, desiredFout;
  212. long fdivise;
  213. long ppmError;
  214. long bestError;
  215. long ftmp;
  216. fref = 1431818; /* frequence XTAL */
  217. pDevice = pDeviceParam;
  218. mgaReadBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_R), init_misc);
  219. misc.var8 = init_misc;
  220. /* special condition: if VCLK is a multiple of MCLK,
  221. * use special programming multiple VCLK=MCLK
  222. */
  223. if ( reg != MEMORY_CLOCK )
  224. {
  225. /*
  226. * 4&3rd case include in same one "for(i=0;...
  227. * at place of check1(), and for(i=1;...)"
  228. *
  229. * 4rd case: MCLK is soo far as VCLK (.5%)
  230. * look for jither problems if both oscillator clock are same or
  231. * closer one from the other, change video frequency to
  232. * use MCLK redirection.
  233. * 3rd case: MCLK is multiple of VCLK
  234. * if mclk is multiple of mclk, divide vclk
  235. * ex. mclk=50MHz, vclk=25MHz,
  236. * vclk(fvco)=mclk(fvco)
  237. * mclk==> 50mhz,
  238. * vclk==> 50mhz/2
  239. */
  240. i_find = NO;
  241. for ( i = 0 ; ( i < NBRE_M_POSSIBLE && i_find == NO ) ; i++ )
  242. {
  243. ftmp = ( fout * 1000L ) * diviseur_m[i];
  244. if ( ( ftmp >= ( presentMclk[iBoard] - (presentMclk[iBoard]/200) ) ) &&
  245. ( ftmp <= ( presentMclk[iBoard] + (presentMclk[iBoard]/200) ) ) )
  246. {
  247. i_find = YES; /* MCLK is multiple of VCLK */
  248. index = i; /* keep divisor value */
  249. }
  250. }
  251. if ( i_find == YES )
  252. {
  253. old_frequency = old_fr_reg[reg];
  254. old_fr_reg[reg] = fout / 1000L;
  255. /*
  256. * We program VCLK since it use same MCLK fvco origin.
  257. * We reprogram only I value in register to use MCLK on
  258. * VCLCK, and m divisor (see ICD2061A for more details).
  259. */
  260. /***** putMclkOnVclk ( reg, index ); *****/
  261. reg_clock[reg].bit.m_diviseur = index;
  262. reg_clock[reg].bit.index_field = 0xF; /* MCLK fvco value */
  263. programme_reg_icd (pDevice, (short)reg, reg_clock[reg].var32);
  264. dummyCallDelai();
  265. selectIcdOutputReg ( reg );
  266. return ( old_frequency ); /* QUIT */
  267. }
  268. }
  269. /***************************************************/
  270. /*
  271. /* MUST ONLY PROGRAM THE REGISTER
  272. /*
  273. /***************************************************/
  274. if ( fout == 0L )
  275. {
  276. switch ( reg )
  277. {
  278. case VIDEO_CLOCK_1:
  279. case VIDEO_CLOCK_2:
  280. misc.sel_reg_output.select = (byte)reg;
  281. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  282. break;
  283. case VIDEO_CLOCK_3:
  284. misc.sel_reg_output.select = 3;
  285. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  286. break;
  287. default:
  288. /* par defaut, (si on a modifie MCLK), on restore VCLK
  289. * initial
  290. */
  291. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), init_misc);
  292. break;
  293. }
  294. return ( NO );
  295. }
  296. /***************************************************/
  297. /*
  298. /* MUST CALCULATE A FREQUENCY
  299. /*
  300. /***************************************************/
  301. desiredFout = fout;
  302. index = 0;
  303. bestError = 99999999; /* dummy start number */
  304. for ( m = 0 ; m < NBRE_M_POSSIBLE ; m++ ) /* for all possible divisors */
  305. {
  306. fdivise = diviseur_m[m];
  307. fvco = fdivise * desiredFout;
  308. if ((fvco < 40000) || (fvco > 120000))
  309. continue;
  310. for ( q = 3 ; q <= 129 ; q++ )
  311. {
  312. if ( ((fref/q) < 20000) || ((fref/q) > 100000))
  313. continue;
  314. p = ((q * fvco * 100) / (2 * fref)) + 1;
  315. if (p < 4 || p > 130)
  316. continue;
  317. /**************************************************
  318. * now that we have all our values
  319. * we determine the true f(output), and its error.
  320. */
  321. trueFout = (2 * fref * p) / (q * fdivise * 100) ;
  322. if (trueFout > desiredFout)
  323. ppmError = trueFout - desiredFout;
  324. else
  325. ppmError = desiredFout - trueFout;
  326. if ( ppmError < bestError )
  327. {
  328. /***************************************************
  329. *
  330. * HO!!! this result is better than the preceding one
  331. *
  332. */
  333. i_find = -1;
  334. for ( i = 0 ; i < NBRE_I_POSSIBLE ; i++ )
  335. {
  336. if ( ( fvco >= limites_i[i] ) && ( fvco <= limites_i[i+1] ) )
  337. i_find = i;
  338. }
  339. if ( i_find != -1 )
  340. {
  341. index = 0; /* reset result table */
  342. result.p = (short)p;
  343. result.q = (short)q;
  344. result.m = (short)m;
  345. result.i = i_find;
  346. result.trueFout = trueFout;
  347. result.fvco = fout; /* keep real value */
  348. result.ppmError = ppmError;
  349. index++; /* find a good value */
  350. bestError = ppmError; /* reset reference erreur */
  351. }
  352. }
  353. }
  354. }
  355. if ( index == 0 )
  356. {
  357. /* restore valeur de depart */
  358. /* outb ( MISC_OUTPUT_WRITE , init_misc ); */
  359. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), init_misc);
  360. }
  361. else
  362. {
  363. programme_clock ( (short)reg, result.p,
  364. result.q,
  365. result.m,
  366. result.i );
  367. selectIcdOutputReg ( reg );
  368. /* SAVE PRESENT FREQUENCY in kHz */
  369. old_frequency = old_fr_reg[reg]; /* RETURN VALUE */
  370. old_fr_reg[reg] = fout / 1000L;
  371. }
  372. dummyCallDelai();
  373. return (old_frequency);
  374. }
  375. /* ======================================================================= */
  376. /*/
  377. * NAME: selectIcdOutputReg ( long reg )
  378. *
  379. * Select desired output register.
  380. *
  381. */
  382. static byte selectIcdOutputReg ( long reg )
  383. {
  384. /********************************************/
  385. /*
  386. /* PROGRAMME CS : clock output select
  387. /*
  388. /********************************************/
  389. switch ( reg )
  390. {
  391. case VIDEO_CLOCK_1:
  392. case VIDEO_CLOCK_2:
  393. misc.sel_reg_output.select = (byte)reg;
  394. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  395. break;
  396. case VIDEO_CLOCK_3:
  397. misc.sel_reg_output.select = 3;
  398. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  399. break;
  400. default: /*** MEMORY CLOCK ***/
  401. /*
  402. * if we modify MCLK, restore VCLK initial value
  403. */
  404. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), init_misc);
  405. presentMclk[iBoard] = result.fvco;
  406. break;
  407. }
  408. dummyCallDelai();
  409. return ( misc.var8 );
  410. }
  411. /* ======================================================================= */
  412. /*/
  413. * NAME: programme_clock ( short p, short q, short m, short reg )
  414. *
  415. * Program the clock of the programmable oscillator for the desired
  416. * frequency.
  417. *
  418. */
  419. dword programme_clock ( short reg, short p, short q, short m, short i )
  420. {
  421. reg_clock [ reg ].var32 = 0;
  422. reg_clock [ reg ].bit.q_prime = q - 2;
  423. reg_clock [ reg ].bit.m_diviseur = m;
  424. reg_clock [ reg ].bit.p_prime = p - 3;
  425. reg_clock [ reg ].bit.index_field = i;
  426. programme_reg_icd ( pDevice, reg, reg_clock [ reg ].var32 );
  427. dummyCallDelai();
  428. return ( reg_clock [ reg ] .var32 );
  429. }
  430. /* ======================================================================= */
  431. /*/
  432. * NAME: programme_reg_icd ( volatile BYTE _Far *pDeviceParam, short reg, dword data )
  433. *
  434. * This routine permits the serial programming of the programmable oscillator
  435. * (ICD2061). It uses the following communication protocol
  436. * (from HARDWARE SPECs):
  437. *
  438. *
  439. * ^ . . . . . .
  440. * | . . . . . .
  441. * | . _ _ _ _ _ ___ ____ ____ ___ _._
  442. * CLK |_____| |_| |_| |_| |_| |___| . |___| . |___| . |___| . |___| .
  443. * | . . . . . .
  444. * | . . . . . .
  445. * | . _____________________ . . ___ . ___________._
  446. * DATA |___| |____________| |________| . .
  447. * +----------------------------------------------------------------->
  448. * | . unlock sequence . start . send 0 . send 1 . stop .
  449. * | . . bit . . . bit .
  450. * |
  451. *
  452. *
  453. *
  454. * Parameters: [0] - reg: address of internal register of the ICD2061 (3 bits).
  455. * [1] - data: data to write in reg (21 bits).
  456. *
  457. */
  458. void programme_reg_icd ( volatile BYTE _Far *pDeviceParam, short reg, dword data )
  459. {
  460. pDevice = pDeviceParam;
  461. send_unlock ();
  462. send_start ();
  463. send_data ( reg, data );
  464. send_stop ();
  465. }
  466. /* ======================================================================= */
  467. /*/
  468. * NAME: send_unlock ( void )
  469. *
  470. * Send unlock sequence
  471. *
  472. */
  473. static void send_unlock ( void )
  474. {
  475. misc.clock_bit.pgmdata = 1;
  476. misc.clock_bit.pgmclk = 0;
  477. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  478. dummyCallDelai();
  479. send_full_clock ();
  480. send_full_clock ();
  481. send_full_clock ();
  482. send_full_clock ();
  483. send_full_clock ();
  484. }
  485. /* ======================================================================= */
  486. /*/
  487. * NAME: send_data ( void )
  488. *
  489. * Sends 21 bits of data + 3 bits for the register.
  490. *
  491. */
  492. static void send_data ( short reg, dword data )
  493. {
  494. short i;
  495. for ( i = 0 ; i < 21 ; i++ )
  496. {
  497. if ( ( data & 1 ) == 1 )
  498. send_1 ();
  499. else
  500. send_0 ();
  501. data >>= 1;
  502. }
  503. for ( i = 0 ; i < 3 ; i++ )
  504. {
  505. if ( ( reg & 1 ) == 1 )
  506. send_1 ();
  507. else
  508. send_0 ();
  509. reg >>= 1;
  510. }
  511. }
  512. /* ======================================================================= */
  513. /*/
  514. * NAME: send_full_clock ( void )
  515. *
  516. * Toggle one full clock (used only by send_unlock()").
  517. *
  518. */
  519. static void send_full_clock ( void )
  520. {
  521. misc.clock_bit.pgmclk = 1;
  522. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  523. /*** delay to be sure to respect the programming setup time of the ICD2061 */
  524. dummyCallDelai();
  525. misc.clock_bit.pgmclk = 0;
  526. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  527. /*** delay to be sure to respect the programming setup time of the ICD2061 */
  528. dummyCallDelai();
  529. }
  530. /* ======================================================================= */
  531. /*/
  532. * NAME: send_start ( void )
  533. *
  534. * Send start sequence
  535. *
  536. */
  537. static void send_start ( void )
  538. {
  539. misc.clock_bit.pgmdata = 0;
  540. misc.clock_bit.pgmclk = 0;
  541. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  542. dummyCallDelai();
  543. send_full_clock ();
  544. misc.clock_bit.pgmdata = 0;
  545. misc.clock_bit.pgmclk = 1;
  546. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  547. dummyCallDelai();
  548. }
  549. /* ======================================================================= */
  550. /*/
  551. * NAME: send_0 ( void )
  552. *
  553. * Send data bit 0 (protocol "MANCHESTER").
  554. *
  555. */
  556. static void send_0 ( void )
  557. {
  558. misc.clock_bit.pgmdata = 0;
  559. misc.clock_bit.pgmclk = 1;
  560. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  561. dummyCallDelai();
  562. misc.clock_bit.pgmdata = 1;
  563. misc.clock_bit.pgmclk = 1;
  564. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  565. dummyCallDelai();
  566. misc.clock_bit.pgmdata = 1;
  567. misc.clock_bit.pgmclk = 0;
  568. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  569. dummyCallDelai();
  570. misc.clock_bit.pgmdata = 0;
  571. misc.clock_bit.pgmclk = 0;
  572. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  573. dummyCallDelai();
  574. misc.clock_bit.pgmdata = 0;
  575. misc.clock_bit.pgmclk = 1;
  576. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  577. dummyCallDelai();
  578. }
  579. /* ======================================================================= */
  580. /*/
  581. * NAME: send_1 ( void )
  582. *
  583. * Send data bit 1 (protocol "MANCHESTER").
  584. *
  585. */
  586. static void send_1 ( void )
  587. {
  588. misc.clock_bit.pgmdata = 0;
  589. misc.clock_bit.pgmclk = 1;
  590. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  591. dummyCallDelai();
  592. misc.clock_bit.pgmdata = 0;
  593. misc.clock_bit.pgmclk = 0;
  594. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  595. dummyCallDelai();
  596. misc.clock_bit.pgmdata = 1;
  597. misc.clock_bit.pgmclk = 0;
  598. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  599. dummyCallDelai();
  600. misc.clock_bit.pgmdata = 1;
  601. misc.clock_bit.pgmclk = 1;
  602. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  603. dummyCallDelai();
  604. }
  605. /* ======================================================================= */
  606. /*/
  607. * NAME: send_stop ( void )
  608. *
  609. * Send stop sequence
  610. *
  611. */
  612. static void send_stop ( void )
  613. {
  614. misc.clock_bit.pgmdata = 1;
  615. misc.clock_bit.pgmclk = 1;
  616. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  617. dummyCallDelai();
  618. misc.clock_bit.pgmdata = 1;
  619. misc.clock_bit.pgmclk = 0;
  620. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  621. dummyCallDelai();
  622. misc.clock_bit.pgmdata = 1;
  623. misc.clock_bit.pgmclk = 1;
  624. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  625. dummyCallDelai();
  626. misc.clock_bit.pgmdata = 0;
  627. misc.clock_bit.pgmclk = 1;
  628. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  629. dummyCallDelai();
  630. }
  631. /* ======================================================================= */
  632. /***************************************************************************/
  633. /*/ setTVP3026Freq ( volatile byte _Far *pDeviceParam, long desiredFout, long reg, word pWidth )
  634. *
  635. * Calculate best value to obtain a frequency output.
  636. * This routine program and select the register.
  637. * If fout is 0, just toggle to the desired
  638. * output register.
  639. *
  640. * Problems :
  641. * Designed : Patrick Servais:94/04/08
  642. *
  643. * Parameters: [0]-desired output frequency (in kHz).
  644. * (0 -> select desired register)
  645. * [1]-register (0, 1, 2 ou 3) to prgram and select.
  646. * (the MCLOCK register (3) can be reprogrammable, but
  647. * is always available for output - no selection is permit).
  648. *
  649. * Call :
  650. *
  651. * Used :
  652. * Modify : Benoit Leblanc
  653. *
  654. * Return : old frequency value
  655. *
  656. * List of modifications :
  657. *
  658. */
  659. long setTVP3026Freq ( volatile byte _Far *pDeviceParam, long fout, long reg, byte pWidth )
  660. {
  661. word i;
  662. short p, pixel_p, pixel_n, q, n, bestN;
  663. int m, pixel_m, bestM, tmp;
  664. short index;
  665. short val;
  666. long old_frequency, z;
  667. long fvco, fTemp, trueFout, desiredFout;
  668. long ppmError;
  669. long bestError;
  670. byte init_misc, dac_rev1;
  671. byte tmpByte, saveByte;
  672. word pixelWidth;
  673. dword power;
  674. dword config200Mhz, fvcoMax;
  675. switch(pWidth)
  676. {
  677. case 0:
  678. pixelWidth = 8;
  679. break;
  680. case 1:
  681. pixelWidth = 16;
  682. break;
  683. case 2:
  684. pixelWidth = 32;
  685. break;
  686. }
  687. /* Hard to 16*/
  688. pDevice = pDeviceParam;
  689. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), 0x01); /* Silicon revision */
  690. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  691. if (tmpByte >= 0x10)
  692. dac_rev1 = 1;
  693. else
  694. dac_rev1 = 0;
  695. /* Read 200Mhz straps saved in config register */
  696. mgaReadDWORD(*(pDevice+TITAN_OFFSET + TITAN_CONFIG), config200Mhz);
  697. if (config200Mhz & 0x00000004)
  698. {
  699. fvcoMax = (dword)220000000; /* 200Mhz support */
  700. }
  701. else
  702. {
  703. fvcoMax = (dword)175000000; /* 200Mhz not support */
  704. }
  705. mgaReadBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_R), init_misc);
  706. misc.var8 = init_misc;
  707. /***************************************************/
  708. /*
  709. /* CALCULATE FREQUENCY
  710. /*
  711. /***************************************************/
  712. bestError = 99999999; /* dummy start number */
  713. fref = 14318180; /* frequence clock ref */
  714. index = 0;
  715. bestError = 5000000;
  716. desiredFout = fout * 1000; /* Scale it from KHz to Hz */
  717. if ((dword) desiredFout>= (fvcoMax >> 1))
  718. p = 0;
  719. else if ((dword) desiredFout>=(fvcoMax >> 2))
  720. p = 1;
  721. else if ((dword) desiredFout>=(fvcoMax >> 3))
  722. p = 2;
  723. else
  724. p = 3;
  725. power = 1;
  726. for(i=0; i<p; i++)
  727. power = power * 2;
  728. for ( n=1;n<=63;n++ )
  729. {
  730. m = (650 - (((((dword)desiredFout*10)/fref) * ((65-n) * power)) / 8)) / 10;
  731. fTemp = fref / (65-n);
  732. fvco = fTemp * 8 * (65-m);
  733. trueFout = fvco / power;
  734. if (trueFout < desiredFout)
  735. ppmError = desiredFout - trueFout;
  736. else
  737. ppmError = trueFout - desiredFout;
  738. if ((ppmError < bestError) &&
  739. (m > 0) && (m <= 63) &&
  740. (fTemp > 500000) &&
  741. ((dword)fvco >= (fvcoMax >> 1) ) && (fvco <= (dword)220000000))
  742. {
  743. index = 1;
  744. bestError = ppmError;
  745. bestM = m;
  746. bestN = n;
  747. }
  748. }
  749. m = bestM;
  750. n = bestN;
  751. fTemp = fref / (65-n);
  752. fvco = fTemp * 8 * (65-m);
  753. {
  754. dword num;
  755. num = ((65 - m)*10) / (65-n);
  756. num = num * 8 * fref;
  757. trueFout = (num / power) / 10;
  758. }
  759. if ( index == 0 ) /* no solution find */
  760. {
  761. /* ***ERROR: setFrequence() NONE RESULT (IMPOSSIBLE?!?) */
  762. /* restore valeur de depart */
  763. old_frequency = 0L; /* ERREUR RETURN */
  764. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), init_misc);
  765. }
  766. else
  767. {
  768. /**********************************************************************
  769. *
  770. * SET THE DESIRED FREQUENCY OUTPUT REGISTER
  771. *
  772. */
  773. switch ( reg )
  774. {
  775. case VIDEO_CLOCK_3: /* NOTE 1: header */
  776. misc.sel_reg_output.select = 3; /* NOTE 1: header */
  777. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), misc.var8);
  778. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PLL_ADDR);
  779. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  780. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte & 0xfc);
  781. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PIX_CLK_DATA );
  782. if (dac_rev1)
  783. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), ((n&0x3f)|0xc0) );
  784. else
  785. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), ((n&0x3f)|0x80) );
  786. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (m&0x3f) );
  787. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), ((p&0x03)|0xf0) );
  788. tmp = 0;
  789. do
  790. {
  791. tmp += 1;
  792. delay_us(10);
  793. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PIX_CLK_DATA);
  794. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  795. tmpByte &= 0x40;
  796. } while((tmpByte != 0x40) && (tmp < 5000));
  797. if((tmp == 5000) && (fout < 1100000) && (fvcoMax == 220000000))
  798. LowerVCO(fout, 0, pWidth, fvcoMax, dac_rev1);
  799. /* searching for loop clock parameters */
  800. n = 65 - ((4*64)/pixelWidth); /* 64 is the Pixel bus Width */
  801. m = 0x3d;
  802. z = ((65L-n)*2750L)/(fout/1000);
  803. q = 0;
  804. p = 3;
  805. if (z <= 200)
  806. p = 0;
  807. else if (z <= 400)
  808. p = 1;
  809. else if (z <= 800)
  810. p = 2;
  811. else if (z <=1600)
  812. p = 3;
  813. else
  814. q = (short)(z/1600);
  815. if (dac_rev1)
  816. n |= 0xc0;
  817. else
  818. n |= 0x80;
  819. if ((dac_rev1 == 0) && (fout <= 175000))
  820. p |= 0xb0;
  821. else
  822. p |= 0xf0;
  823. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_MCLK_CTL);
  824. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  825. val = tmpByte;
  826. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), ((val&0xf8)|q) | 0x20);
  827. if ((pWidth == TITAN_PWIDTH_PW24) && (dac_rev1))
  828. {
  829. if (desiredFout >= 50000000)
  830. {n = 0xf9; p = 0xf9; m=0x3e;}
  831. else
  832. {n = 0xf9; p = 0xfb; m=0x3e;}
  833. }
  834. else if ((pWidth == TITAN_PWIDTH_PW24) && (dac_rev1 == 0))
  835. {
  836. if (desiredFout >= 50000000)
  837. {n = 0xb9; p = 0xf9; m=0x3e;}
  838. else
  839. {n = 0xb9; p = 0xfb; m=0x3e;}
  840. }
  841. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PLL_ADDR);
  842. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  843. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte & 0xcf);
  844. /* DAT Patrick Servais, on ajoute ce qui suis */
  845. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_LOAD_CLK_DATA);
  846. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), 0);
  847. delay_us(100L);
  848. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), 0);
  849. delay_us(100L);
  850. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), 0);
  851. delay_us(100L);
  852. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PLL_ADDR);
  853. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  854. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte & 0xcf);
  855. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_LOAD_CLK_DATA);
  856. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (byte)n);
  857. delay_us(100L);
  858. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (byte)m);
  859. delay_us(100L);
  860. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (byte)p);
  861. delay_us(100L);
  862. tmp = 0;
  863. do
  864. {
  865. tmp += 1;
  866. delay_us(10);
  867. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_LOAD_CLK_DATA);
  868. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  869. tmpByte &= 0x40;
  870. } while((tmpByte != 0x40) && (tmp < 5000));
  871. if(tmp == 5000)
  872. LowerVCO(fout, 1, pWidth, fvcoMax, dac_rev1);
  873. old_frequency = old_fr_reg[reg]; /* RETURN VALUE */
  874. old_fr_reg[reg] = trueFout / 1000L;
  875. /* SAVE PRESENT FREQUENCY in kHz */
  876. break;
  877. /*******************************************************************
  878. *
  879. * the programmation line is used to modify register internal value
  880. * of TVP3026, and to select output video register (with internal
  881. * muxer) at the end of programmation. For the system clock
  882. * MCLOCK programmation, at the end, we put on programmation line
  883. * the initial value of the video register.
  884. *
  885. */
  886. case MEMORY_CLOCK:
  887. /* par defaut, (si on a modifie MCLK), on restore VCLK
  888. * initial
  889. */
  890. mgaReadBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_R), saveByte);
  891. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PLL_ADDR);
  892. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), 0xfc);
  893. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PIX_CLK_DATA);
  894. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), pixel_n);
  895. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PLL_ADDR);
  896. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), 0xfd);
  897. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PIX_CLK_DATA);
  898. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), pixel_m);
  899. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PLL_ADDR);
  900. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), 0xfe);
  901. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PIX_CLK_DATA);
  902. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), pixel_p);
  903. /*------------*/
  904. /* 1st step */
  905. /*------------*/
  906. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PLL_ADDR);
  907. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), 0xfc);
  908. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PIX_CLK_DATA);
  909. if (dac_rev1)
  910. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), ((n&0x3f)|0xc0));
  911. else
  912. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), ((n&0x3f)|0x80));
  913. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (m&0x3f));
  914. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), ((p&0x03)|0xb0));
  915. do
  916. {
  917. delay_us(1);
  918. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  919. tmpByte &= 0x40;
  920. } while(tmpByte != 0x40);
  921. /*------------*/
  922. /* 2d step */
  923. /*------------*/
  924. /* Select programmable clock */
  925. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), 0x0f);
  926. delay_us(2000);
  927. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PLL_ADDR);
  928. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), 0xff);
  929. do
  930. {
  931. delay_us(1);
  932. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  933. tmpByte &= 0x40;
  934. } while(tmpByte != 0x40);
  935. /* Select internal pclk instead of external pclk0 */
  936. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_CLK_SEL);
  937. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), 5);
  938. /*------------*/
  939. /* 3rd step */
  940. /*------------*/
  941. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_MCLK_CTL);
  942. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), val);
  943. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (val&0xe7));
  944. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (val&0xe7)|0x08);
  945. /*------------*/
  946. /* 4th step */
  947. /*------------*/
  948. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PLL_ADDR);
  949. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), 0xf3);
  950. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_MEM_CLK_DATA);
  951. if (dac_rev1)
  952. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), ((n&0x3f)|0xc0));
  953. else
  954. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), ((n&0x3f)|0x80));
  955. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (m&0x3f));
  956. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), ((p&0x03)|0xb0));
  957. delay_us(3500);
  958. do
  959. {
  960. delay_us(1);
  961. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  962. tmpByte &= 0x40;
  963. } while(tmpByte != 0x40);
  964. /*------------*/
  965. /* 5th step */
  966. /*------------*/
  967. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_MCLK_CTL);
  968. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (val&0xe7)|0x10);
  969. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (val&0xe7)|0x18);
  970. /*------------*/
  971. /* 6th step */
  972. /*------------*/
  973. /* Restore clock select */
  974. mgaWriteBYTE(*(pDevice + TITAN_OFFSET + TITAN_MISC_OUT_W), saveByte);
  975. /* Reselect external pclk0 */
  976. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_CLK_SEL);
  977. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), 7);
  978. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PLL_ADDR);
  979. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), 0xfc);
  980. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PIX_CLK_DATA);
  981. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (byte)pixel_n);
  982. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (byte)pixel_m);
  983. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (byte)pixel_p);
  984. do
  985. {
  986. delay_us(1);
  987. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  988. tmpByte &= 0x40;
  989. } while(tmpByte != 0x40);
  990. old_fr_reg[reg] = trueFout / 1000L; /* SAVE PRESENT FREQUENCY */
  991. break;
  992. default:
  993. /***ERROR: REGISTER ICD UNKNOWN: */
  994. old_frequency = 0L; /* ERROR RETURN */
  995. break;
  996. }
  997. }
  998. /* wait 10ms before quit....this is not suppose
  999. * to necessary outside of the programmation
  1000. * register, but, well, we are not too secure
  1001. */
  1002. dummyCallDelai();
  1003. /* delay ( 10 ); */
  1004. return ( old_frequency );
  1005. }
  1006. void LowerVCO(long Fout, byte pll, byte pwidth, dword vcomax, byte dacrev1)
  1007. {
  1008. word i;
  1009. short p, q, n, bestN;
  1010. int m, bestM;
  1011. short val;
  1012. long z;
  1013. long fvco, fvco_l, fTemp, trueFout, desiredFout;
  1014. long ppmError;
  1015. long bestError;
  1016. byte tmpByte;
  1017. word pixelwidth, div_ratio;
  1018. dword power;
  1019. dword fvcomax;
  1020. switch(pwidth)
  1021. {
  1022. case 0:
  1023. pixelwidth = 8;
  1024. div_ratio = 8;
  1025. break;
  1026. case 1:
  1027. pixelwidth = 16;
  1028. div_ratio = 4;
  1029. break;
  1030. case 2:
  1031. pixelwidth = 32;
  1032. div_ratio = 2;
  1033. break;
  1034. }
  1035. desiredFout = Fout * 1000; /* Scale it from KHz to Hz */
  1036. switch(pll)
  1037. {
  1038. case 0:
  1039. fvcomax = (dword)175000000; /* Patch pour eviter la Deadzone */
  1040. bestError = 99999999; /* dummy start number */
  1041. fref = 14318180; /* frequence clock ref */
  1042. if ((dword)desiredFout>= (fvcomax >> 1))
  1043. p = 0;
  1044. else if ((dword)desiredFout>=(fvcomax >> 2))
  1045. p = 1;
  1046. else if ((dword)desiredFout>=(fvcomax >> 3))
  1047. p = 2;
  1048. else
  1049. p = 3;
  1050. power = 1;
  1051. for(i=0; i<p; i++)
  1052. power = power * 2;
  1053. for ( n=40;n<=62;n++ )
  1054. {
  1055. m = (650 - (((((dword)desiredFout*10)/fref) * ((65-n) * power)) / 8)) / 10;
  1056. fTemp = fref / (65 - n);
  1057. fvco = fTemp * 8 * (65 - m);
  1058. trueFout = fvco / power;
  1059. if (trueFout < desiredFout)
  1060. ppmError = desiredFout - trueFout;
  1061. else
  1062. ppmError = trueFout - desiredFout;
  1063. if ((ppmError < bestError) &&
  1064. (m > 0) && (m <= 63) &&
  1065. (fTemp > 500000) &&
  1066. ((dword)fvco >= (fvcomax >> 1) ) && (fvco <= (dword)220000000))
  1067. {
  1068. bestError = ppmError;
  1069. bestM = m;
  1070. bestN = n;
  1071. }
  1072. }
  1073. m = bestM;
  1074. n = bestN;
  1075. {
  1076. dword num;
  1077. num = ((65 - m)*10) / (65-n);
  1078. num = num * 8 * fref;
  1079. trueFout = (num / power) / 10;
  1080. }
  1081. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PLL_ADDR);
  1082. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  1083. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte & 0xfc);
  1084. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PIX_CLK_DATA );
  1085. if (dacrev1)
  1086. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), ((n&0x3f)|0xc0) );
  1087. else
  1088. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), ((n&0x3f)|0x80) );
  1089. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (m&0x3f) );
  1090. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), ((p&0x03)|0xf0) );
  1091. do
  1092. {
  1093. delay_us(10);
  1094. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PIX_CLK_DATA);
  1095. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  1096. tmpByte &= 0x40;
  1097. } while(tmpByte != 0x40);
  1098. break;
  1099. case 1:
  1100. /* searching for loop clock parameters */
  1101. n = 65 - ((4*64)/pixelwidth); /* 64 is the Pixel bus Width */
  1102. m = 0x3d;
  1103. z = ((65L-(long)n)*2750L)/(Fout/1000);
  1104. q = 0;
  1105. p = 3;
  1106. if (z <= 200)
  1107. p = 0;
  1108. else if (z <= 400)
  1109. p = 1;
  1110. else if (z <= 800)
  1111. p = 2;
  1112. else if (z <=1600)
  1113. p = 3;
  1114. else
  1115. q = (short)(z/1600);
  1116. /* Patch: si vco du loop clock pll est > 180 MHz, on le divise par deux */
  1117. /* pour ne plus qu'il soit dans la dead zone */
  1118. div_ratio = div_ratio * 10;
  1119. if (pwidth == TITAN_PWIDTH_PW24)
  1120. div_ratio = 80/3; /* meilleurs precision */
  1121. fvco_l = ((Fout/div_ratio) << p) * (2*(q+1)) * 10;
  1122. if ((p > 0) && (fvco_l > 180000))
  1123. p = p-1;
  1124. if (dacrev1)
  1125. n |= 0xc0;
  1126. else
  1127. n |= 0x80;
  1128. if ((dacrev1 == 0) && (Fout <= 175000))
  1129. p |= 0xb0;
  1130. else
  1131. p |= 0xf0;
  1132. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_MCLK_CTL);
  1133. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  1134. val = tmpByte;
  1135. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), ((val&0xf8)|q) | 0x20);
  1136. if ((pwidth == TITAN_PWIDTH_PW24) && (dacrev1))
  1137. {
  1138. if (desiredFout >= 50000000)
  1139. {n = 0xf9; p = 0xf9; m=0x3e;}
  1140. else
  1141. {n = 0xf9; p = 0xfb; m=0x3e;}
  1142. }
  1143. else if ((pwidth == TITAN_PWIDTH_PW24) && (dacrev1 == 0))
  1144. {
  1145. if (desiredFout >= 50000000)
  1146. {n = 0xb9; p = 0xf9; m=0x3e;}
  1147. else
  1148. {n = 0xb9; p = 0xfb; m=0x3e;}
  1149. }
  1150. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_PLL_ADDR);
  1151. mgaReadBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte);
  1152. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), tmpByte & 0xcf);
  1153. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_INDEX), TVP3026_LOAD_CLK_DATA);
  1154. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (byte)n);
  1155. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (byte)m);
  1156. mgaWriteBYTE(*(pDevice + RAMDAC_OFFSET + TVP3026_DATA), (byte)p);
  1157. break;
  1158. }
  1159. }