Leaked source code of windows server 2003
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.

1450 lines
43 KiB

  1. //***************************************************************************
  2. //
  3. // Module Name:
  4. //
  5. // video.c
  6. //
  7. // Abstract:
  8. //
  9. // This module contains the code to setup the timing values for chips
  10. // and RAMDACs
  11. //
  12. // Environment:
  13. //
  14. // Kernel mode
  15. //
  16. //
  17. // Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  18. // Copyright (c) 1995-1999 Microsoft Corporation. All Rights Reserved.
  19. //
  20. //***************************************************************************
  21. #include "permedia.h"
  22. VOID CheckRGBClockInteraction(PULONG PixelClock, PULONG SystemClock);
  23. ULONG TVP4020_CalculateMNPForClock(PVOID HwDeviceExtension,
  24. ULONG RefClock,
  25. ULONG ReqClock,
  26. BOOLEAN IsPixClock,
  27. ULONG MinClock,
  28. ULONG MaxClock,
  29. ULONG *rM,
  30. ULONG *rN,
  31. ULONG *rP);
  32. ULONG Dac_SeparateClocks(ULONG PixelClock, ULONG SystemClock);
  33. BOOLEAN InitializeVideo(PHW_DEVICE_EXTENSION HwDeviceExtension,
  34. PP2_VIDEO_FREQUENCIES VideoMode);
  35. ULONG P2RD_CalculateMNPForClock(PVOID HwDeviceExtension,
  36. ULONG RefClock,
  37. ULONG ReqClock,
  38. ULONG *rM,
  39. ULONG *rN,
  40. ULONG *rP);
  41. BOOLEAN Program_P2RD(PHW_DEVICE_EXTENSION HwDeviceExtension,
  42. PP2_VIDEO_FREQUENCIES VideoMode,
  43. ULONG Hsp,
  44. ULONG Vsp,
  45. ULONG RefClkSpeed,
  46. PULONG pSystemClock,
  47. PULONG pPixelClock);
  48. #if defined(ALLOC_PRAGMA)
  49. #pragma alloc_text(PAGE,CheckRGBClockInteraction)
  50. #pragma alloc_text(PAGE,TVP4020_CalculateMNPForClock)
  51. #pragma alloc_text(PAGE,Dac_SeparateClocks)
  52. #pragma alloc_text(PAGE,InitializeVideo)
  53. #pragma alloc_text(PAGE,P2RD_CalculateMNPForClock)
  54. #pragma alloc_text(PAGE,Program_P2RD)
  55. #endif
  56. VOID
  57. CheckRGBClockInteraction(
  58. PULONG PixelClock,
  59. PULONG SystemClock
  60. )
  61. /*++
  62. Routine Description:
  63. Ensure the output frequencies do not interract. The following must be true
  64. fHigher != n*fLower +/- 3MHz, for all N >= 1
  65. 3MHz is the safe limit. 2MHz is sufficient.
  66. Arguments:
  67. PixelClock - Pointer to the clock rate for pixel output.
  68. SystemClock - Pointer to the clock rate driving the Permedia2.
  69. Return Value:
  70. If the clocks interact then they are adjusted and returned in the pointer
  71. values.
  72. --*/
  73. {
  74. PLONG fLower, fHigher;
  75. LONG nfLower;
  76. if (*PixelClock < *SystemClock)
  77. {
  78. fLower = PixelClock;
  79. fHigher = SystemClock;
  80. }
  81. else
  82. {
  83. fLower = SystemClock;
  84. fHigher = PixelClock;
  85. }
  86. while (TRUE)
  87. {
  88. nfLower = *fLower;
  89. while (nfLower - 20000 <= *fHigher)
  90. {
  91. if (*fHigher <= (nfLower + 20000))
  92. {
  93. //
  94. // 100KHz adjustments
  95. //
  96. if (*fHigher > nfLower)
  97. {
  98. *fLower -= 1000;
  99. *fHigher += 1000;
  100. }
  101. else
  102. {
  103. *fLower += 1000;
  104. *fHigher -= 1000;
  105. }
  106. break;
  107. }
  108. nfLower += *fLower;
  109. }
  110. if ((nfLower - 20000) > *fHigher)
  111. break;
  112. }
  113. }
  114. #define INITIALFREQERR 100000
  115. ULONG
  116. TVP4020_CalculateMNPForClock(
  117. PVOID HwDeviceExtension,
  118. ULONG RefClock, // In 100Hz units
  119. ULONG ReqClock, // In 100Hz units
  120. BOOLEAN IsPixClock, // is this the pixel or the sys clock
  121. ULONG MinClock, // Min VCO rating
  122. ULONG MaxClock, // Max VCO rating
  123. ULONG *rM, // M Out
  124. ULONG *rN, // N Out
  125. ULONG *rP // P Out
  126. )
  127. {
  128. ULONG M, N, P;
  129. ULONG VCO, Clock;
  130. LONG freqErr, lowestFreqErr = INITIALFREQERR;
  131. ULONG ActualClock = 0;
  132. for (N = 2; N <= 14; N++)
  133. {
  134. for (M = 2; M <= 255; M++)
  135. {
  136. VCO = ((RefClock * M) / N);
  137. if ((VCO < MinClock) || (VCO > MaxClock))
  138. continue;
  139. for (P = 0; P <= 4; P++)
  140. {
  141. Clock = VCO >> P;
  142. freqErr = (Clock - ReqClock);
  143. if (freqErr < 0)
  144. {
  145. //
  146. // PixelClock gets rounded up always so monitor reports
  147. // correct frequency.
  148. // TMM: I have changed this because it causes our refresh
  149. // rate to be incorrect and some DirectDraw waitForVBlank
  150. // tests fail.
  151. // if (IsPixClock)
  152. // continue;
  153. //
  154. freqErr = -freqErr;
  155. }
  156. if (freqErr < lowestFreqErr)
  157. {
  158. //
  159. // Only replace if error is less; keep N small!
  160. //
  161. *rM = M;
  162. *rN = N;
  163. *rP = P;
  164. ActualClock = Clock;
  165. lowestFreqErr = freqErr;
  166. //
  167. // Return if we found an exact match
  168. //
  169. if (freqErr == 0)
  170. return(ActualClock);
  171. }
  172. }
  173. }
  174. }
  175. return(ActualClock);
  176. }
  177. ULONG Dac_SeparateClocks(ULONG PixelClock, ULONG SystemClock)
  178. {
  179. ULONG M, N, P;
  180. //
  181. // Ensure frequencies do not interract
  182. //
  183. P = 1;
  184. do
  185. {
  186. M = P * SystemClock;
  187. if ((M > PixelClock - 10000) && (M < PixelClock + 10000))
  188. {
  189. //
  190. // Frequencies do interract. We can either change the
  191. // PixelClock or change the System clock to avoid it.
  192. //
  193. SystemClock = (PixelClock - 10000) / P;
  194. }
  195. N = P * PixelClock;
  196. if ((N > SystemClock - 10000) && (N < SystemClock + 10000))
  197. {
  198. //
  199. // Frequencies do interract. We can either change the
  200. // PixelClock or change the System clock to avoid it.
  201. //
  202. SystemClock = N - 10000;
  203. }
  204. P++;
  205. } while ((M < PixelClock + 30000) || (N < SystemClock + 30000));
  206. return (SystemClock);
  207. }
  208. BOOLEAN
  209. InitializeVideo(
  210. PHW_DEVICE_EXTENSION HwDeviceExtension,
  211. PP2_VIDEO_FREQUENCIES VideoMode
  212. )
  213. {
  214. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  215. PVIDEO_MODE_INFORMATION VideoModeInfo = &VideoMode->ModeEntry->ModeInformation;
  216. ULONG index;
  217. ULONG color;
  218. ULONG ulValue;
  219. ULONG ulValue1;
  220. UCHAR pixelCtrl;
  221. UCHAR pixelFormat;
  222. ULONG dShift;
  223. VESA_TIMING_STANDARD VESATimings;
  224. ULONG Htot, Hss, Hse, Hbe, Hsp;
  225. ULONG Vtot, Vss, Vse, Vbe, Vsp;
  226. ULONG PixelClock, Freq;
  227. ULONG VCO;
  228. ULONG RefClkSpeed, SystemClock; // Speed of clocks in 100Hz units
  229. ULONG VTGPolarity;
  230. ULONG M, N, P, C, Q;
  231. LONG gateAdjust;
  232. BOOLEAN SecondTry;
  233. USHORT usData;
  234. ULONG DacDepth, depth, xRes, yRes;
  235. ULONG xStride;
  236. ULONG ClrComp5, ClrComp6;
  237. ULONG pixelData;
  238. P2_DECL;
  239. TVP4020_DECL;
  240. depth = VideoMode->BitsPerPel;
  241. xRes = VideoMode->ScreenWidth;
  242. yRes = VideoMode->ScreenHeight;
  243. Freq = VideoMode->ScreenFrequency;
  244. //
  245. // For timing calculations need full depth in bits
  246. //
  247. if ((DacDepth = depth) == 15)
  248. {
  249. DacDepth = 16;
  250. }
  251. else if (depth == 12)
  252. {
  253. DacDepth = 32;
  254. }
  255. //
  256. // convert screen stride from bytes to pixels
  257. //
  258. xStride = (8 * VideoModeInfo->ScreenStride) / DacDepth;
  259. //
  260. // Ensure minimum frequency of 60 Hz
  261. //
  262. if (Freq < 60)
  263. {
  264. DEBUG_PRINT((2, "Frequency raised to minimum of 60Hz\n"));
  265. Freq = 60;
  266. }
  267. DEBUG_PRINT((2, "depth %d, xres %d, yres %d, freq %d\n",
  268. depth, xRes, yRes, Freq));
  269. //
  270. // Get the video timing, from the registry, if an entry exists, or from
  271. // the list of defaults, if it doesn't.
  272. //
  273. if (!GetVideoTiming ( HwDeviceExtension,
  274. xRes,
  275. yRes,
  276. Freq,
  277. depth,
  278. &VESATimings ))
  279. {
  280. DEBUG_PRINT((1, "GetVideoTiming failed."));
  281. return (FALSE);
  282. }
  283. //
  284. // We have got a valid set of VESA timigs
  285. //
  286. Htot = VESATimings.HTot;
  287. Hss = VESATimings.HFP ;
  288. Hse = Hss + VESATimings.HST;
  289. Hbe = Hse + VESATimings.HBP;
  290. Hsp = VESATimings.HSP;
  291. Vtot = VESATimings.VTot;
  292. Vss = VESATimings.VFP ;
  293. Vse = Vss + VESATimings.VST;
  294. Vbe = Vse + VESATimings.VBP;
  295. Vsp = VESATimings.VSP;
  296. //
  297. // if we're zooming by 2 in Y then double the vertical timing values.
  298. //
  299. if (VideoModeInfo->DriverSpecificAttributeFlags & CAPS_ZOOM_Y_BY2)
  300. {
  301. Vtot *= 2;
  302. Vss *= 2;
  303. Vse *= 2;
  304. Vbe *= 2;
  305. }
  306. //
  307. // Calculate Pixel Clock in 100 Hz units
  308. //
  309. PixelClock = (Htot * Vtot * Freq * 8) / 100;
  310. pixelData = PixelClock * (DacDepth / 8);
  311. if (pixelData > P2_MAX_PIXELDATA)
  312. {
  313. //
  314. // Failed pixelData validation
  315. //
  316. return (FALSE);
  317. }
  318. RefClkSpeed = hwDeviceExtension->RefClockSpeed / 100; // 100Hz units
  319. SystemClock = hwDeviceExtension->ChipClockSpeed / 100; // 100Hz units
  320. //
  321. // We do some basic initialization before setting up MCLK.
  322. //
  323. //
  324. // disable the video control register
  325. //
  326. hwDeviceExtension->bVTGRunning = FALSE;
  327. hwDeviceExtension->VideoControl = 0;
  328. VideoPortWriteRegisterUlong( VIDEO_CONTROL,
  329. hwDeviceExtension->VideoControl );
  330. //
  331. // Enable graphics mode, disable VGA
  332. //
  333. VideoPortWriteRegisterUchar( PERMEDIA_MMVGA_INDEX_REG,
  334. PERMEDIA_VGA_CTRL_INDEX);
  335. usData = (USHORT)VideoPortReadRegisterUchar(PERMEDIA_MMVGA_DATA_REG);
  336. usData &= ~PERMEDIA_VGA_ENABLE;
  337. usData = (usData << 8) | PERMEDIA_VGA_CTRL_INDEX;
  338. VideoPortWriteRegisterUshort(PERMEDIA_MMVGA_INDEX_REG, usData);
  339. //
  340. // Setup Ramdac.
  341. //
  342. if (hwDeviceExtension->DacId == TVP4020_RAMDAC)
  343. {
  344. //
  345. // No separate S/W reset for P2 pixel unit
  346. //
  347. //
  348. // 1x64x64, cursor 1, ADDR[9:8] = 00, cursor off
  349. //
  350. TVP4020_WRITE_INDEX_REG(__TVP4020_CURSOR_CONTROL, 0x40);
  351. //
  352. // Redundant here; we just cleared the CCR above
  353. //
  354. TVP4020_LOAD_CURSOR_CTRL(TVP4020_CURSOR_OFF);
  355. TVP4020_SET_CURSOR_COLOR0(0, 0, 0);
  356. TVP4020_SET_CURSOR_COLOR1(0xFF, 0xFF, 0xFF);
  357. //
  358. // P2 sets the sync polarity in the RAMDAC rather than VideoControl
  359. // 7.5 IRE, 8-bit data
  360. //
  361. ulValue = ((Hsp ? 0x0 : 0x1) << 2) | ((Vsp ? 0x0 : 0x1) << 3) | 0x12;
  362. TVP4020_WRITE_INDEX_REG(__TVP4020_MISC_CONTROL, ulValue);
  363. TVP4020_WRITE_INDEX_REG(__TVP4020_MODE_CONTROL, 0x00); // Mode Control
  364. TVP4020_WRITE_INDEX_REG(__TVP4020_CK_CONTROL, 0x00); // Color-Key Control
  365. TVP4020_WRITE_INDEX_REG(__TVP4020_PALETTE_PAGE, 0x00); // Palette page
  366. //
  367. // No zoom on P2 pixel unit
  368. //
  369. // No separate multiplex control on P2 pixel unit
  370. //
  371. // Start TI TVP4020 programming
  372. //
  373. switch (depth)
  374. {
  375. case 8:
  376. //
  377. // RGB, graphics, Color Index 8
  378. //
  379. TVP4020_WRITE_INDEX_REG(__TVP4020_COLOR_MODE, 0x30);
  380. if( hwDeviceExtension->Capabilities & CAPS_8BPP_RGB )
  381. {
  382. ULONG Red, Green, Blue ;
  383. //
  384. // load BGR 2:3:3 ramp into LUT
  385. //
  386. for (index = 0; index <= 0xff; ++index)
  387. {
  388. Red = bPal8[index & 0x07];
  389. Green = bPal8[(index >> 3 ) &0x07];
  390. Blue = bPal4[(index >> 6 ) &0x03];
  391. //
  392. // EXTRA!! EXTRA!! EXTRA!!!
  393. // After more research on more pleasing appearance
  394. // we now added more grays, now we look not only for
  395. // EXACT match of RED and GREEN, we consider it gray
  396. // even when they differ by 1.
  397. // Added 15-Jan-1996 -by- [olegsher]
  398. //
  399. // Maybe it's a special case of gray ?
  400. //
  401. if (abs((index & 0x07) - ((index >> 3 ) &0x07)) <= 1)
  402. {
  403. //
  404. // This is a tricky part:
  405. // the Blue field in BGR 2:3:3 color goes thru
  406. // steps 00, 01, 10, 11 (Binary)
  407. //
  408. // the Red and Green go thru 000, 001, 010, 011,
  409. // 100, 101, 110, 111 (Binary)
  410. //
  411. // We load the special gray values ONLY when Blue
  412. // color is close in intensity to both Green and Red,
  413. // i.e. Blue = 01, Green = 010 or 011,
  414. // Blue = 10, Green = 100 or 101,
  415. //
  416. if ((((index >> 1) & 0x03) == ((index >> 6 ) & 0x03 )) ||
  417. (((index >> 4) & 0x03) == ((index >> 6 ) & 0x03 )) ||
  418. ((Green == Red) && ( abs((index & 0x07) - ((index >> 5) & 0x06)) <= 1 )))
  419. {
  420. if( Blue || (Green == Red)) // Don't mess with dark colors
  421. {
  422. color = (Red * 2 + Green * 3 + Blue) / 6;
  423. Red = Green = Blue = color;
  424. }
  425. }
  426. }
  427. LUT_CACHE_SETRGB (index, Red, Green, Blue);
  428. }
  429. }
  430. else
  431. {
  432. for (index = 0; index <= 0xff; ++index)
  433. LUT_CACHE_SETRGB (index, index, index, index);
  434. }
  435. break;
  436. case 15:
  437. case 16:
  438. //
  439. // True color w/gamma, RGB, graphics, 5:5:5:1
  440. //
  441. pixelCtrl = 0xB4;
  442. //
  443. // True-color w/gamma, RGB, graphics, 5:6:5
  444. //
  445. if (depth == 16)
  446. pixelCtrl |= 0x02;
  447. TVP4020_WRITE_INDEX_REG(__TVP4020_COLOR_MODE, pixelCtrl);
  448. //
  449. // load linear ramp into LUT
  450. //
  451. for (index = 0; index <= 0xff; ++index)
  452. {
  453. ClrComp5 = (index & 0xF8) | (index >> 5);
  454. ClrComp6 = (index & 0xFC) | (index >> 6);
  455. LUT_CACHE_SETRGB (index,
  456. ClrComp5,
  457. depth == 16 ? ClrComp6 : ClrComp5, ClrComp5);
  458. }
  459. break;
  460. case 24:
  461. case 32:
  462. //
  463. // True color w/gamma, RGB, graphics, 8:8:8:8
  464. //
  465. pixelCtrl = 0xB8;
  466. //
  467. // True color w/gamma, RGB, graphics, packed-24
  468. //
  469. if (depth == 24)
  470. pixelCtrl |= 0x01;
  471. TVP4020_WRITE_INDEX_REG(__TVP4020_COLOR_MODE, pixelCtrl);
  472. //
  473. // load linear ramp into LUT
  474. // standard 888 ramps
  475. //
  476. for (index = 0; index <= 0xff; ++index)
  477. LUT_CACHE_SETRGB (index, index, index, index);
  478. break;
  479. default:
  480. DEBUG_PRINT((2, "Cannot set RAMDAC for bad depth %d\n", depth));
  481. break;
  482. }
  483. //
  484. // if the clocks are in danger of interacting adjust the system clock
  485. //
  486. SystemClock = Dac_SeparateClocks(PixelClock, SystemClock);
  487. //
  488. // Program system clock. This controls the speed of the Permedia 2.
  489. //
  490. SystemClock = TVP4020_CalculateMNPForClock(
  491. HwDeviceExtension,
  492. RefClkSpeed, // In 100Hz units
  493. SystemClock, // In 100Hz units
  494. FALSE, // SysClock
  495. 1500000, // Min VCO rating
  496. 3000000, // Max VCO rating
  497. &M, // M Out
  498. &N, // N Out
  499. &P); // P Out
  500. if (SystemClock == 0)
  501. {
  502. DEBUG_PRINT((1, "TVP4020_CalculateMNPForClock failed\n"));
  503. return(FALSE);
  504. }
  505. //
  506. // Can change P2 MCLK directly without switching to PCLK
  507. //
  508. // Program the Mclk PLL
  509. //
  510. // test mode: forces MCLK to constant high
  511. //
  512. TVP4020_WRITE_INDEX_REG(__TVP4020_MEMCLK_REG_3, 0x06);
  513. TVP4020_WRITE_INDEX_REG(__TVP4020_MEMCLK_REG_2, N); // N
  514. TVP4020_WRITE_INDEX_REG(__TVP4020_MEMCLK_REG_1, M); // M
  515. TVP4020_WRITE_INDEX_REG(__TVP4020_MEMCLK_REG_3, P | 0x08);// P / Enable
  516. C = 1000000;
  517. do
  518. {
  519. TVP4020_READ_INDEX_REG(__TVP4020_MEMCLK_STATUS, ulValue); // Status
  520. } while ((!(ulValue & (1 << 4))) && (--C));
  521. //
  522. // No zoom on P2 pixel unit
  523. //
  524. // Program Pixel Clock to the correct value for the required resolution
  525. //
  526. PixelClock = TVP4020_CalculateMNPForClock(
  527. HwDeviceExtension,
  528. RefClkSpeed, // In 100Hz units
  529. PixelClock, // In 100Hz units
  530. TRUE, // Pixel Clock
  531. 1500000, // Min VCO rating
  532. 3000000, // Max VCO rating
  533. &M, // M Out
  534. &N, // N Out
  535. &P); // P Out
  536. if (PixelClock == 0)
  537. {
  538. DEBUG_PRINT((1, "TVP4020_CalculateMNPForClock failed\n"));
  539. return(FALSE);
  540. }
  541. //
  542. // Pixel Clock
  543. //
  544. TVP4020_WRITE_INDEX_REG(__TVP4020_PIXCLK_REG_C3, 0x06); // RESET PCLK PLL
  545. TVP4020_WRITE_INDEX_REG(__TVP4020_PIXCLK_REG_C2, N ); // N
  546. TVP4020_WRITE_INDEX_REG(__TVP4020_PIXCLK_REG_C1, M); // M
  547. TVP4020_WRITE_INDEX_REG(__TVP4020_PIXCLK_REG_C3, P | 0x08);// Enable PCLK
  548. M = 1000000;
  549. do
  550. {
  551. TVP4020_READ_INDEX_REG(__TVP4020_PIXCLK_STATUS, ulValue);
  552. } while ((!(ulValue & (1 << 4))) && (--M));
  553. //
  554. // No Loop Clock on P2
  555. //
  556. TVP4020_SET_PIXEL_READMASK (0xff);
  557. //
  558. // TMM: there is a rule that says if you muck about with the
  559. // MCLK then you must set up the MEM_CONFIG register again.
  560. //
  561. }
  562. else if (hwDeviceExtension->DacId == P2RD_RAMDAC)
  563. {
  564. if( !Program_P2RD( HwDeviceExtension,
  565. VideoMode,
  566. Hsp,
  567. Vsp,
  568. RefClkSpeed,
  569. &SystemClock,
  570. &PixelClock))
  571. return(FALSE);
  572. }
  573. //
  574. // Set the LUT cache size and set the first entry to zero, then
  575. // write the LUT cache to the LUT
  576. //
  577. LUT_CACHE_SETSIZE (256);
  578. LUT_CACHE_SETFIRST (0);
  579. (void) Permedia2SetColorLookup ( hwDeviceExtension,
  580. &(hwDeviceExtension->LUTCache.LUTCache),
  581. sizeof (hwDeviceExtension->LUTCache),
  582. TRUE, // Always update RAMDAC
  583. FALSE ); // Don't Update cache entries
  584. //
  585. // Setup VTG
  586. //
  587. ulValue = 3; // RAMDAC pll pins for VClkCtl
  588. if ((hwDeviceExtension->DacId == P2RD_RAMDAC) ||
  589. (hwDeviceExtension->DacId == TVP4020_RAMDAC))
  590. {
  591. ULONG PCIDelay;
  592. //
  593. // TMM: The algorithm we used to calculate PCIDelay for P1 doesn't
  594. // work for P2, frequent mode changes might cause hangups.
  595. // So I took the value used by the BIOS for AGP and PCI systems
  596. // and used that one. It works fine on PCI and VGA PCs.
  597. //
  598. PCIDelay = 32;
  599. ulValue |= (PCIDelay << 2);
  600. }
  601. else
  602. {
  603. DEBUG_PRINT((1, "Invalid RAMDAC type! \n"));
  604. }
  605. //
  606. // dShift is now used as a multiplier, instead of a shift count.
  607. // This is to support P2 packed-24 mode where the VESA horizontal
  608. // timing values need to be multiplied by a non-power-of-two multiplier.
  609. //
  610. if ((hwDeviceExtension->DacId == TVP4020_RAMDAC && DacDepth > 8) ||
  611. hwDeviceExtension->DacId == P2RD_RAMDAC)
  612. {
  613. dShift = DacDepth >> 3; // 64-bit pixel bus
  614. }
  615. else
  616. {
  617. dShift = DacDepth >> 2; // 32-bit pixel bus
  618. }
  619. //
  620. // must load HgEnd before ScreenBase
  621. //
  622. VideoPortWriteRegisterUlong(HG_END, Hbe * dShift);
  623. //
  624. // Need to set up RAMDAC pll pins
  625. //
  626. VideoPortWriteRegisterUlong(V_CLK_CTL, ulValue);
  627. VideoPortWriteRegisterUlong(SCREEN_BASE, 0);
  628. VideoPortWriteRegisterUlong(SCREEN_STRIDE, (xStride >> 3) * (DacDepth >> 3)); // 64-bit units
  629. VideoPortWriteRegisterUlong(H_TOTAL, (Htot * dShift) - 1);
  630. VideoPortWriteRegisterUlong(HS_START, Hss * dShift);
  631. VideoPortWriteRegisterUlong(HS_END, Hse * dShift);
  632. VideoPortWriteRegisterUlong(HB_END, Hbe * dShift);
  633. VideoPortWriteRegisterUlong(V_TOTAL, Vtot - 1);
  634. VideoPortWriteRegisterUlong(VS_START, Vss - 1);
  635. VideoPortWriteRegisterUlong(VS_END, Vse - 1);
  636. VideoPortWriteRegisterUlong(VB_END, Vbe);
  637. {
  638. ULONG highWater, newChipConfig, oldChipConfig;
  639. #define videoFIFOSize 32
  640. #define videoFIFOLoWater 8
  641. #define videoFIFOLatency 26
  642. //
  643. // Calculate the high-water, by taking into account
  644. // the pixel clock, the pxiel size, add 1 for luck
  645. //
  646. highWater = (((videoFIFOLatency * PixelClock * DacDepth) /
  647. (64 * SystemClock )) + 1);
  648. //
  649. // Trim the highwater, make sure it's not bigger than the FIFO size
  650. //
  651. if (highWater > videoFIFOSize)
  652. highWater = videoFIFOSize;
  653. highWater = videoFIFOSize - highWater;
  654. //
  655. // Make sure the highwater is greater than the low water mark.
  656. //
  657. if (highWater <= videoFIFOLoWater)
  658. highWater = videoFIFOLoWater + 1;
  659. ulValue = (highWater << 8) | videoFIFOLoWater;
  660. VideoPortWriteRegisterUlong(VIDEO_FIFO_CTL, ulValue);
  661. //
  662. // select the appropriate Delta clock source
  663. //
  664. #define SCLK_SEL_PCI (0x0 << 10) // Delta Clk == PCI Clk
  665. #define SCLK_SEL_PCIHALF (0x1 << 10) // Delta Clk == 1/2 PCI Clk
  666. #define SCLK_SEL_MCLK (0x2 << 10) // Delta Clk == MClk
  667. #define SCLK_SEL_MCLKHALF (0x3 << 10) // Delta Clk == 1/2 MClk
  668. #define SCLK_SEL_MASK (0x3 << 10)
  669. if (VideoPortGetRegistryParameters(HwDeviceExtension,
  670. L"P2DeltaClockMode",
  671. FALSE,
  672. Permedia2RegistryCallback,
  673. &ulValue) == NO_ERROR)
  674. {
  675. ulValue <<= 10;
  676. ulValue &= SCLK_SEL_MASK;
  677. }
  678. else
  679. {
  680. if((hwDeviceExtension->deviceInfo.RevisionId == PERMEDIA2A_REV_ID) &&
  681. (hwDeviceExtension->PciSpeed == 66))
  682. {
  683. ulValue = SCLK_SEL_PCI;
  684. }
  685. else
  686. {
  687. //
  688. // This is the default value
  689. //
  690. ulValue = SCLK_SEL_MCLKHALF;
  691. }
  692. }
  693. newChipConfig = oldChipConfig = VideoPortReadRegisterUlong(CHIP_CONFIG);
  694. newChipConfig &= ~SCLK_SEL_MASK;
  695. newChipConfig |= ulValue;
  696. VideoPortWriteRegisterUlong(CHIP_CONFIG, newChipConfig);
  697. }
  698. //
  699. // Enable video out and set sync polaritys to active high.
  700. // P2 uses 64-bit pixel bus for modes > 8BPP
  701. //
  702. VTGPolarity = (1 << 5) | (1 << 3) | 1;
  703. if (hwDeviceExtension->DacId == P2RD_RAMDAC || DacDepth > 8)
  704. {
  705. //
  706. // P2ST always uses 64-bit pixel bus
  707. // P2 uses 64-bit pixel bus for modes > 8BPP
  708. //
  709. VTGPolarity |= (1 << 16);
  710. }
  711. if (VideoModeInfo->DriverSpecificAttributeFlags & CAPS_ZOOM_Y_BY2)
  712. VTGPolarity |= (1 << 2);
  713. hwDeviceExtension->VideoControl = VTGPolarity;
  714. VideoPortWriteRegisterUlong(VIDEO_CONTROL, hwDeviceExtension->VideoControl);
  715. DEBUG_PRINT((2, "Loaded Permedia timing registers:\n"));
  716. DEBUG_PRINT((2, "\tVClkCtl: 0x%x\n", 3));
  717. DEBUG_PRINT((2, "\tScreenBase: 0x%x\n", 0));
  718. DEBUG_PRINT((2, "\tScreenStride: 0x%x\n", xStride >> (3 - (DacDepth >> 4))));
  719. DEBUG_PRINT((2, "\tHTotal: 0x%x\n", (Htot << dShift) - 1));
  720. DEBUG_PRINT((2, "\tHsStart: 0x%x\n", Hss << dShift));
  721. DEBUG_PRINT((2, "\tHsEnd: 0x%x\n", Hse << dShift));
  722. DEBUG_PRINT((2, "\tHbEnd: 0x%x\n", Hbe << dShift));
  723. DEBUG_PRINT((2, "\tHgEnd: 0x%x\n", Hbe << dShift));
  724. DEBUG_PRINT((2, "\tVTotal: 0x%x\n", Vtot - 1));
  725. DEBUG_PRINT((2, "\tVsStart: 0x%x\n", Vss - 1));
  726. DEBUG_PRINT((2, "\tVsEnd: 0x%x\n", Vse - 1));
  727. DEBUG_PRINT((2, "\tVbEnd: 0x%x\n", Vbe));
  728. DEBUG_PRINT((2, "\tVideoControl: 0x%x\n", VTGPolarity));
  729. //
  730. // record the final chip clock in the registry
  731. //
  732. SystemClock *= 100;
  733. VideoPortSetRegistryParameters(HwDeviceExtension,
  734. L"HardwareInformation.CurrentChipClockSpeed",
  735. &SystemClock,
  736. sizeof(ULONG));
  737. hwDeviceExtension->bVTGRunning = TRUE;
  738. DEBUG_PRINT((2, "InitializeVideo Finished\n"));
  739. return(TRUE);
  740. }
  741. ULONG P2RD_CalculateMNPForClock(
  742. PVOID HwDeviceExtension,
  743. ULONG RefClock, // In 100Hz units
  744. ULONG ReqClock, // In 100Hz units
  745. ULONG *rM, // M Out (feedback scaler)
  746. ULONG *rN, // N Out (prescaler)
  747. ULONG *rP // P Out (postscaler)
  748. )
  749. /*++
  750. Routine Description:
  751. Calculates prescaler, feedback scaler and postscaler values for the
  752. STMACRO PLL61-1M used by P2RD.
  753. --*/
  754. {
  755. const ULONG fMinVCO = 1280000; // min fVCO is 128MHz (in 100Hz units)
  756. const ULONG fMaxVCO = 2560000; // max fVCO is 256MHz (in 100Hz units)
  757. const ULONG fMinINTREF = 10000; // min fINTREF is 1MHz (in 100Hz units)
  758. const ULONG fMaxINTREF = 20000; // max fINTREF is 2MHz (in 100Hz units)
  759. ULONG M, N, P;
  760. ULONG fINTREF;
  761. ULONG fVCO;
  762. ULONG ActualClock;
  763. int Error;
  764. int LowestError = INITIALFREQERR;
  765. BOOLEAN bFoundFreq = FALSE;
  766. int LoopCount;
  767. for(P = 0; P <= 4; ++P)
  768. {
  769. ULONG fVCOLowest, fVCOHighest;
  770. //
  771. // it's pointless going through the main loop if all values of N
  772. // produce an fVCO outside the acceptable range
  773. //
  774. N = 1;
  775. M = (N * (1 << P) * ReqClock) / RefClock;
  776. fVCOLowest = (RefClock * M) / N;
  777. N = 255;
  778. M = (N * (1 << P) * ReqClock) / RefClock;
  779. fVCOHighest = (RefClock * M) / N;
  780. if(fVCOHighest < fMinVCO || fVCOLowest > fMaxVCO)
  781. continue;
  782. for(N = 1; N <= 255; ++N)
  783. {
  784. fINTREF = RefClock / N;
  785. if(fINTREF < fMinINTREF || fINTREF > fMaxINTREF)
  786. {
  787. if(fINTREF > fMaxINTREF)
  788. {
  789. //
  790. // hopefully we'll get into range as the prescale
  791. // value increases
  792. //
  793. continue;
  794. }
  795. else
  796. {
  797. //
  798. // already below minimum and it'll only get worse:
  799. // move to the next postscale value
  800. //
  801. break;
  802. }
  803. }
  804. M = (N * (1 << P) * ReqClock) / RefClock;
  805. if(M > 255)
  806. {
  807. //
  808. // M, N & P registers are only 8 bits wide
  809. //
  810. break;
  811. }
  812. //
  813. // we can expect rounding errors in calculating M, which will
  814. // always be rounded down. So we'll checkout our calculated
  815. // value of M along with (M+1)
  816. //
  817. for(LoopCount = (M == 255) ? 1 : 2; --LoopCount >= 0; ++M)
  818. {
  819. fVCO = (RefClock * M) / N;
  820. if(fVCO >= fMinVCO && fVCO <= fMaxVCO)
  821. {
  822. ActualClock = fVCO / (1 << P);
  823. Error = ActualClock - ReqClock;
  824. if(Error < 0)
  825. Error = -Error;
  826. if(Error < LowestError)
  827. {
  828. bFoundFreq = TRUE;
  829. LowestError = Error;
  830. *rM = M;
  831. *rN = N;
  832. *rP = P;
  833. if(Error == 0)
  834. goto Done;
  835. }
  836. }
  837. }
  838. }
  839. }
  840. Done:
  841. if(bFoundFreq)
  842. ActualClock = (RefClock * *rM) / (*rN * (1 << *rP));
  843. else
  844. ActualClock = 0;
  845. return(ActualClock);
  846. }
  847. BOOLEAN Program_P2RD(PHW_DEVICE_EXTENSION HwDeviceExtension,
  848. PP2_VIDEO_FREQUENCIES VideoMode,
  849. ULONG Hsp,
  850. ULONG Vsp,
  851. ULONG RefClkSpeed,
  852. PULONG pSystemClock,
  853. PULONG pPixelClock )
  854. /*++
  855. Routine Description:
  856. initializes the P2RD registers and programs the DClk (pixel clock)
  857. and MClk (system clock) PLLs. After programming the MClk, the
  858. contents of all registers in the graphics core, the memory controller
  859. and the video control should be assumed to be undefined
  860. --*/
  861. {
  862. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  863. PVIDEO_MODE_INFORMATION VideoModeInfo = &VideoMode->ModeEntry->ModeInformation;
  864. ULONG DacDepth, depth;
  865. LONG mpxAdjust;
  866. ULONG index;
  867. ULONG color;
  868. ULONG ulValue;
  869. UCHAR pixelCtrl;
  870. ULONG M, N, P;
  871. P2_DECL;
  872. P2RD_DECL;
  873. depth = VideoMode->BitsPerPel;
  874. //
  875. // For timing calculations need full depth in bits
  876. //
  877. if ((DacDepth = depth) == 15)
  878. DacDepth = 16;
  879. else if (depth == 12)
  880. DacDepth = 32;
  881. VideoPortWriteRegisterUlong(P2RD_INDEX_CONTROL,
  882. P2RD_IDX_CTL_AUTOINCREMENT_ENABLED);
  883. ulValue = (Hsp ? P2RD_SYNC_CONTROL_HSYNC_ACTIVE_HIGH : P2RD_SYNC_CONTROL_HSYNC_ACTIVE_LOW) |
  884. (Vsp ? P2RD_SYNC_CONTROL_VSYNC_ACTIVE_HIGH : P2RD_SYNC_CONTROL_VSYNC_ACTIVE_LOW);
  885. if (VideoModeInfo->DriverSpecificAttributeFlags & CAPS_ZOOM_X_BY2)
  886. {
  887. //
  888. // it's a really low resolution (e.g. 320x200) so enable pixel
  889. // doubling in the RAMDAC (we'll enable line doubling in the
  890. // pixel unit too)
  891. //
  892. P2RD_LOAD_INDEX_REG(P2RD_MISC_CONTROL,
  893. P2RD_MISC_CONTROL_HIGHCOLORRES |
  894. P2RD_MISC_CONTROL_DIRECT_COLOR_ENABLED |
  895. P2RD_MISC_CONTROL_PIXEL_DOUBLE);
  896. }
  897. else
  898. {
  899. P2RD_LOAD_INDEX_REG(P2RD_MISC_CONTROL,
  900. P2RD_MISC_CONTROL_HIGHCOLORRES |
  901. P2RD_MISC_CONTROL_DIRECT_COLOR_ENABLED);
  902. }
  903. P2RD_LOAD_INDEX_REG(P2RD_SYNC_CONTROL, ulValue);
  904. P2RD_LOAD_INDEX_REG(P2RD_DAC_CONTROL,
  905. P2RD_DAC_CONTROL_BLANK_PEDESTAL_ENABLED);
  906. ulValue = 0;
  907. if (VideoModeInfo->DriverSpecificAttributeFlags & CAPS_ZOOM_X_BY2)
  908. {
  909. ulValue |= P2RD_CURSOR_CONTROL_DOUBLE_X;
  910. }
  911. if (VideoModeInfo->DriverSpecificAttributeFlags & CAPS_ZOOM_Y_BY2)
  912. {
  913. ulValue |= P2RD_CURSOR_CONTROL_DOUBLE_Y;
  914. }
  915. P2RD_LOAD_INDEX_REG(P2RD_CURSOR_CONTROL, ulValue);
  916. P2RD_LOAD_INDEX_REG(P2RD_CURSOR_MODE, 0);
  917. P2RD_LOAD_INDEX_REG(P2RD_CURSOR_X_LOW, 0);
  918. P2RD_LOAD_INDEX_REG(P2RD_CURSOR_X_HIGH, 0);
  919. P2RD_LOAD_INDEX_REG(P2RD_CURSOR_Y_LOW, 0);
  920. P2RD_LOAD_INDEX_REG(P2RD_CURSOR_Y_HIGH, 0xff);
  921. P2RD_LOAD_INDEX_REG(P2RD_CURSOR_HOTSPOT_X, 0);
  922. P2RD_LOAD_INDEX_REG(P2RD_CURSOR_HOTSPOT_Y, 0);
  923. P2RD_LOAD_INDEX_REG(P2RD_PAN, 0);
  924. //
  925. // the first 3-color cursor is the mini cursor which is always
  926. // black & white. Set it up here
  927. //
  928. P2RD_CURSOR_PALETTE_CURSOR_RGB(0, 0x00,0x00,0x00);
  929. P2RD_CURSOR_PALETTE_CURSOR_RGB(1, 0xff,0xff,0xff);
  930. //
  931. // stop dot and memory clocks
  932. //
  933. P2RD_LOAD_INDEX_REG(P2RD_DCLK_CONTROL, 0);
  934. P2RD_LOAD_INDEX_REG(P2RD_MCLK_CONTROL, 0);
  935. if (VideoModeInfo->DriverSpecificAttributeFlags & CAPS_ZOOM_X_BY2)
  936. {
  937. //
  938. // we're doubling each pixel so we double the pixel clock too
  939. // NB. the PixelDouble field of RDMiscControl needs to be set also)
  940. //
  941. *pPixelClock *= 2;
  942. }
  943. *pPixelClock = P2RD_CalculateMNPForClock( HwDeviceExtension,
  944. RefClkSpeed,
  945. *pPixelClock,
  946. &M,
  947. &N,
  948. &P );
  949. if(*pPixelClock == 0)
  950. {
  951. DEBUG_PRINT((1, "P2RD_CalculateMNPForClock(PixelClock) failed\n"));
  952. return(FALSE);
  953. }
  954. //
  955. // load both copies of the dot clock with our times (DCLK0 & DCLK1
  956. // reserved for VGA only)
  957. //
  958. P2RD_LOAD_INDEX_REG(P2RD_DCLK2_PRE_SCALE, N);
  959. P2RD_LOAD_INDEX_REG(P2RD_DCLK2_FEEDBACK_SCALE, M);
  960. P2RD_LOAD_INDEX_REG(P2RD_DCLK2_POST_SCALE, P);
  961. P2RD_LOAD_INDEX_REG(P2RD_DCLK3_PRE_SCALE, N);
  962. P2RD_LOAD_INDEX_REG(P2RD_DCLK3_FEEDBACK_SCALE, M);
  963. P2RD_LOAD_INDEX_REG(P2RD_DCLK3_POST_SCALE, P);
  964. *pSystemClock = P2RD_CalculateMNPForClock( HwDeviceExtension,
  965. RefClkSpeed,
  966. *pSystemClock,
  967. &M,
  968. &N,
  969. &P );
  970. if(*pSystemClock == 0)
  971. {
  972. DEBUG_PRINT((1, "P2RD_CalculateMNPForClock(SystemClock) failed\n"));
  973. return(FALSE);
  974. }
  975. //
  976. // load the system clock
  977. //
  978. P2RD_LOAD_INDEX_REG(P2RD_MCLK_PRE_SCALE, N);
  979. P2RD_LOAD_INDEX_REG(P2RD_MCLK_FEEDBACK_SCALE, M);
  980. P2RD_LOAD_INDEX_REG(P2RD_MCLK_POST_SCALE, P);
  981. //
  982. // enable the dot clock
  983. //
  984. P2RD_LOAD_INDEX_REG(P2RD_DCLK_CONTROL,
  985. P2RD_DCLK_CONTROL_ENABLED | P2RD_DCLK_CONTROL_RUN);
  986. M = 0x100000;
  987. do
  988. {
  989. P2RD_READ_INDEX_REG(P2RD_DCLK_CONTROL, ulValue);
  990. }
  991. while((ulValue & P2RD_DCLK_CONTROL_LOCKED) == FALSE && --M);
  992. if((ulValue & P2RD_DCLK_CONTROL_LOCKED) == FALSE)
  993. {
  994. DEBUG_PRINT((1, "Program_P2RD: PixelClock failed to lock\n"));
  995. return(FALSE);
  996. }
  997. //
  998. // enable the system clock
  999. //
  1000. P2RD_LOAD_INDEX_REG(P2RD_MCLK_CONTROL,
  1001. P2RD_MCLK_CONTROL_ENABLED | P2RD_MCLK_CONTROL_RUN);
  1002. M = 0x100000;
  1003. do
  1004. {
  1005. P2RD_READ_INDEX_REG(P2RD_MCLK_CONTROL, ulValue);
  1006. }
  1007. while((ulValue & P2RD_MCLK_CONTROL_LOCKED) == FALSE && --M);
  1008. if((ulValue & P2RD_MCLK_CONTROL_LOCKED) == FALSE)
  1009. {
  1010. DEBUG_PRINT((1, "Program_P2RD: SystemClock failed to lock\n"));
  1011. return(FALSE);
  1012. }
  1013. switch (depth)
  1014. {
  1015. case 8:
  1016. P2RD_READ_INDEX_REG(P2RD_MISC_CONTROL, ulValue);
  1017. ulValue &= ~P2RD_MISC_CONTROL_DIRECT_COLOR_ENABLED;
  1018. P2RD_LOAD_INDEX_REG(P2RD_MISC_CONTROL, ulValue);
  1019. P2RD_LOAD_INDEX_REG(P2RD_PIXEL_SIZE, P2RD_PIXEL_SIZE_8BPP);
  1020. if (hwDeviceExtension->Capabilities & CAPS_8BPP_RGB)
  1021. {
  1022. ULONG Red, Green, Blue ;
  1023. P2RD_LOAD_INDEX_REG(P2RD_COLOR_FORMAT,
  1024. P2RD_COLOR_FORMAT_8BPP | P2RD_COLOR_FORMAT_RGB);
  1025. for (index = 0; index <= 0xff; ++index)
  1026. {
  1027. Red = bPal8[index & 0x07];
  1028. Green = bPal8[(index >> 3 ) & 0x07];
  1029. Blue = bPal4[(index >> 6 ) & 0x03];
  1030. if( Red == Green) // Maybe it's a special case of gray ?
  1031. {
  1032. //
  1033. // This is a tricky part:
  1034. // the Blue field in BGR 2:3:3 color goes thru
  1035. // steps 00, 01, 10, 11 (Binary)
  1036. // the Red and Green go thru 000, 001, 010, 011,
  1037. // 100, 101, 110, 111 (Binary)
  1038. // We load the special gray values ONLY when Blue
  1039. // color is close in intensity to both Green and Red,
  1040. // i.e. Blue = 01, Green = 010 or 011,
  1041. // Blue = 10, Green = 100 or 101,
  1042. //
  1043. if ( ((index >> 1) & 0x03) == ((index >> 6 ) & 0x03 ) )
  1044. {
  1045. Blue = Red;
  1046. }
  1047. }
  1048. LUT_CACHE_SETRGB (index, Red, Green, Blue);
  1049. }
  1050. }
  1051. else
  1052. {
  1053. //
  1054. // Color indexed mode
  1055. //
  1056. P2RD_LOAD_INDEX_REG(P2RD_COLOR_FORMAT,
  1057. P2RD_COLOR_FORMAT_CI8 | P2RD_COLOR_FORMAT_RGB);
  1058. }
  1059. break;
  1060. case 15:
  1061. case 16:
  1062. P2RD_LOAD_INDEX_REG(P2RD_PIXEL_SIZE, P2RD_PIXEL_SIZE_16BPP);
  1063. #if GAMMA_CORRECTION
  1064. P2RD_READ_INDEX_REG(P2RD_MISC_CONTROL, ulValue);
  1065. ulValue &= ~P2RD_MISC_CONTROL_DIRECT_COLOR_ENABLED;
  1066. P2RD_LOAD_INDEX_REG(P2RD_MISC_CONTROL, ulValue);
  1067. //
  1068. // load linear ramp into LUT as default
  1069. //
  1070. for (index = 0; index <= 0xff; ++index)
  1071. LUT_CACHE_SETRGB (index, index, index, index);
  1072. pixelCtrl = 0;
  1073. #else
  1074. P2RD_READ_INDEX_REG(P2RD_MISC_CONTROL, ulValue);
  1075. ulValue |= P2RD_MISC_CONTROL_DIRECT_COLOR_ENABLED;
  1076. P2RD_LOAD_INDEX_REG(P2RD_MISC_CONTROL, ulValue);
  1077. pixelCtrl = P2RD_COLOR_FORMAT_LINEAR_EXT;
  1078. #endif
  1079. pixelCtrl |=
  1080. (depth == 16) ? P2RD_COLOR_FORMAT_16BPP : P2RD_COLOR_FORMAT_15BPP;
  1081. pixelCtrl |= P2RD_COLOR_FORMAT_RGB;
  1082. P2RD_LOAD_INDEX_REG(P2RD_COLOR_FORMAT, pixelCtrl);
  1083. break;
  1084. case 12:
  1085. case 24:
  1086. case 32:
  1087. P2RD_LOAD_INDEX_REG(P2RD_PIXEL_SIZE, P2RD_PIXEL_SIZE_32BPP);
  1088. P2RD_LOAD_INDEX_REG(P2RD_COLOR_FORMAT,
  1089. P2RD_COLOR_FORMAT_32BPP | P2RD_COLOR_FORMAT_RGB);
  1090. if (depth == 12)
  1091. {
  1092. USHORT cacheIndex;
  1093. P2RD_READ_INDEX_REG(P2RD_MISC_CONTROL, ulValue);
  1094. ulValue &= ~P2RD_MISC_CONTROL_DIRECT_COLOR_ENABLED;
  1095. P2RD_LOAD_INDEX_REG(P2RD_MISC_CONTROL, ulValue);
  1096. //
  1097. // use auto-increment to load a ramp into entries 0 to 15
  1098. //
  1099. for (index = 0, cacheIndex = 0;
  1100. index <= 0xff;
  1101. index += 0x11, cacheIndex++)
  1102. {
  1103. LUT_CACHE_SETRGB (index, index, index, index);
  1104. }
  1105. //
  1106. // load ramp in every 16th entry from 16 to 240
  1107. //
  1108. color = 0x11;
  1109. for (index = 0x10; index <= 0xf0; index += 0x10, color += 0x11)
  1110. LUT_CACHE_SETRGB (index, color, color, color);
  1111. P2RD_SET_PIXEL_READMASK(0x0f);
  1112. }
  1113. else
  1114. {
  1115. #if GAMMA_CORRECTION
  1116. P2RD_READ_INDEX_REG(P2RD_MISC_CONTROL, ulValue);
  1117. ulValue &= ~P2RD_MISC_CONTROL_DIRECT_COLOR_ENABLED;
  1118. P2RD_LOAD_INDEX_REG(P2RD_MISC_CONTROL, ulValue);
  1119. //
  1120. // load linear ramp into LUT as default
  1121. //
  1122. for (index = 0; index <= 0xff; ++index)
  1123. LUT_CACHE_SETRGB (index, index, index, index);
  1124. #else
  1125. P2RD_READ_INDEX_REG(P2RD_MISC_CONTROL, ulValue);
  1126. ulValue |= P2RD_MISC_CONTROL_DIRECT_COLOR_ENABLED;
  1127. P2RD_LOAD_INDEX_REG(P2RD_MISC_CONTROL, ulValue);
  1128. #endif // GAMMA_CORRECTION
  1129. }
  1130. break;
  1131. default:
  1132. DEBUG_PRINT((1, "bad depth %d passed to Program_P2RD\n", depth));
  1133. return(FALSE);
  1134. }
  1135. return(TRUE);
  1136. }