smiLynxEM.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838
  1. /*
  2. * (C) Copyright 1997-2002 ELTEC Elektronik AG
  3. * Frank Gottschling <fgottschling@eltec.de>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. /*
  8. * smiLynxEM.c
  9. *
  10. * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator
  11. *
  12. * modification history
  13. * --------------------
  14. * 04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>.
  15. *
  16. * 18-03-2004 - Unify videomodes handling with the ct69000
  17. * - The video output can be set via the variable "videoout"
  18. * in the environment.
  19. * videoout=1 output on LCD
  20. * videoout=2 output on CRT (default value)
  21. * <p.aubert@staubli.com>
  22. */
  23. #include <common.h>
  24. #include <pci.h>
  25. #include <video_fb.h>
  26. #include "videomodes.h"
  27. /*
  28. * Export Graphic Device
  29. */
  30. GraphicDevice smi;
  31. /*
  32. * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
  33. */
  34. #define VIDEO_MEM_SIZE 0x400000
  35. /*
  36. * ISA mapped regs
  37. */
  38. #define SMI_INDX_C4 (pGD->isaBase + 0x03c4) /* index reg */
  39. #define SMI_DATA_C5 (pGD->isaBase + 0x03c5) /* data reg */
  40. #define SMI_INDX_D4 (pGD->isaBase + 0x03d4) /* index reg */
  41. #define SMI_DATA_D5 (pGD->isaBase + 0x03d5) /* data reg */
  42. #define SMI_ISR1 (pGD->isaBase + 0x03ca)
  43. #define SMI_INDX_CE (pGD->isaBase + 0x03ce) /* index reg */
  44. #define SMI_DATA_CF (pGD->isaBase + 0x03cf) /* data reg */
  45. #define SMI_LOCK_REG (pGD->isaBase + 0x03c3) /* unlock/lock ext crt reg */
  46. #define SMI_MISC_REG (pGD->isaBase + 0x03c2) /* misc reg */
  47. #define SMI_LUT_MASK (pGD->isaBase + 0x03c6) /* lut mask reg */
  48. #define SMI_LUT_START (pGD->isaBase + 0x03c8) /* lut start index */
  49. #define SMI_LUT_RGB (pGD->isaBase + 0x03c9) /* lut colors auto incr.*/
  50. #define SMI_INDX_ATTR (pGD->isaBase + 0x03c0) /* attributes index reg */
  51. /*
  52. * Video processor control
  53. */
  54. typedef struct {
  55. unsigned int control;
  56. unsigned int colorKey;
  57. unsigned int colorKeyMask;
  58. unsigned int start;
  59. unsigned short offset;
  60. unsigned short width;
  61. unsigned int fifoPrio;
  62. unsigned int fifoERL;
  63. unsigned int YUVtoRGB;
  64. } SmiVideoProc;
  65. /*
  66. * Video window control
  67. */
  68. typedef struct {
  69. unsigned short top;
  70. unsigned short left;
  71. unsigned short bottom;
  72. unsigned short right;
  73. unsigned int srcStart;
  74. unsigned short width;
  75. unsigned short offset;
  76. unsigned char hStretch;
  77. unsigned char vStretch;
  78. } SmiVideoWin;
  79. /*
  80. * Capture port control
  81. */
  82. typedef struct {
  83. unsigned int control;
  84. unsigned short topClip;
  85. unsigned short leftClip;
  86. unsigned short srcHeight;
  87. unsigned short srcWidth;
  88. unsigned int srcBufStart1;
  89. unsigned int srcBufStart2;
  90. unsigned short srcOffset;
  91. unsigned short fifoControl;
  92. } SmiCapturePort;
  93. /*
  94. * Register values for common video modes
  95. */
  96. static char SMI_SCR[] = {
  97. /* all modes */
  98. 0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x15, 0x90,
  99. 0x17, 0x20, 0x18, 0xb1, 0x19, 0x00,
  100. };
  101. static char SMI_EXT_CRT[] = {
  102. 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
  103. 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00,
  104. };
  105. static char SMI_ATTR [] = {
  106. 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05,
  107. 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b,
  108. 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x41, 0x11, 0x00,
  109. 0x12, 0x0f, 0x13, 0x00, 0x14, 0x00,
  110. };
  111. static char SMI_GCR[18] = {
  112. 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40,
  113. 0x06, 0x05, 0x07, 0x0f, 0x08, 0xff,
  114. };
  115. static char SMI_SEQR[] = {
  116. 0x00, 0x00, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e, 0x00, 0x03,
  117. };
  118. static char SMI_PCR [] = {
  119. 0x20, 0x04, 0x21, 0x30, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00,
  120. };
  121. static char SMI_MCR[] = {
  122. 0x60, 0x01, 0x61, 0x00,
  123. #ifdef CONFIG_HMI1001
  124. 0x62, 0x74, /* Memory type is not configured by pins on HMI1001 */
  125. #endif
  126. };
  127. static char SMI_HCR[] = {
  128. 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
  129. 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00,
  130. };
  131. /*******************************************************************************
  132. *
  133. * Write SMI ISA register
  134. */
  135. static void smiWrite (unsigned short index, char reg, char val)
  136. {
  137. register GraphicDevice *pGD = (GraphicDevice *)&smi;
  138. out8 ((pGD->isaBase + index), reg);
  139. out8 ((pGD->isaBase + index + 1), val);
  140. }
  141. /*******************************************************************************
  142. *
  143. * Write a table of SMI ISA register
  144. */
  145. static void smiLoadRegs (
  146. unsigned int iReg,
  147. unsigned int dReg,
  148. char *regTab,
  149. unsigned int tabSize
  150. )
  151. {
  152. register GraphicDevice *pGD = (GraphicDevice *)&smi;
  153. register int i;
  154. for (i=0; i<tabSize; i+=2) {
  155. if (iReg == SMI_INDX_ATTR) {
  156. /* Reset the Flip Flop */
  157. in8 (SMI_ISR1);
  158. out8 (iReg, regTab[i]);
  159. out8 (iReg, regTab[i+1]);
  160. } else {
  161. out8 (iReg, regTab[i]);
  162. out8 (dReg, regTab[i+1]);
  163. }
  164. }
  165. }
  166. /*******************************************************************************
  167. *
  168. * Init capture port registers
  169. */
  170. static void smiInitCapturePort (void)
  171. {
  172. SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
  173. register GraphicDevice *pGD = (GraphicDevice *)&smi;
  174. register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP;
  175. out32r ((pGD->cprBase + 0x0004), ((pCP->topClip<<16) | pCP->leftClip));
  176. out32r ((pGD->cprBase + 0x0008), ((pCP->srcHeight<<16) | pCP->srcWidth));
  177. out32r ((pGD->cprBase + 0x000c), pCP->srcBufStart1/8);
  178. out32r ((pGD->cprBase + 0x0010), pCP->srcBufStart2/8);
  179. out32r ((pGD->cprBase + 0x0014), pCP->srcOffset/8);
  180. out32r ((pGD->cprBase + 0x0018), pCP->fifoControl);
  181. out32r ((pGD->cprBase + 0x0000), pCP->control);
  182. }
  183. /*******************************************************************************
  184. *
  185. * Init video processor registers
  186. */
  187. static void smiInitVideoProcessor (void)
  188. {
  189. SmiVideoProc smiVP = { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed };
  190. SmiVideoWin smiVW = { 0, 0, 599, 799, 0, 1600, 0, 0, 0 };
  191. register GraphicDevice *pGD = (GraphicDevice *)&smi;
  192. register SmiVideoProc *pVP = (SmiVideoProc *)&smiVP;
  193. register SmiVideoWin *pVWin = (SmiVideoWin *)&smiVW;
  194. pVP->width = pGD->plnSizeX * pGD->gdfBytesPP;
  195. pVP->control |= pGD->gdfIndex << 16;
  196. pVWin->bottom = pGD->winSizeY - 1;
  197. pVWin->right = pGD->winSizeX - 1;
  198. pVWin->width = pVP->width;
  199. /* color key */
  200. out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
  201. /* color key mask */
  202. out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
  203. /* data src start adrs */
  204. out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
  205. /* data width and offset */
  206. out32r ((pGD->vprBase + 0x0010),
  207. ((pVP->offset / 8 * pGD->gdfBytesPP) << 16) |
  208. (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
  209. /* video window 1 */
  210. out32r ((pGD->vprBase + 0x0014),
  211. ((pVWin->top << 16) | pVWin->left));
  212. out32r ((pGD->vprBase + 0x0018),
  213. ((pVWin->bottom << 16) | pVWin->right));
  214. out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
  215. out32r ((pGD->vprBase + 0x0020),
  216. (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
  217. out32r ((pGD->vprBase + 0x0024),
  218. (((pVWin->hStretch) << 8) | pVWin->vStretch));
  219. /* video window 2 */
  220. out32r ((pGD->vprBase + 0x0028),
  221. ((pVWin->top << 16) | pVWin->left));
  222. out32r ((pGD->vprBase + 0x002c),
  223. ((pVWin->bottom << 16) | pVWin->right));
  224. out32r ((pGD->vprBase + 0x0030),
  225. pVWin->srcStart / 8);
  226. out32r ((pGD->vprBase + 0x0034),
  227. (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
  228. out32r ((pGD->vprBase + 0x0038),
  229. (((pVWin->hStretch) << 8) | pVWin->vStretch));
  230. /* fifo prio control */
  231. out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
  232. /* fifo empty request levell */
  233. out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
  234. /* conversion constant */
  235. out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
  236. /* vpr control word */
  237. out32r ((pGD->vprBase + 0x0000), pVP->control);
  238. }
  239. /******************************************************************************
  240. *
  241. * Init drawing engine registers
  242. */
  243. static void smiInitDrawingEngine (void)
  244. {
  245. GraphicDevice *pGD = (GraphicDevice *)&smi;
  246. unsigned int val;
  247. /* don't start now */
  248. out32r ((pGD->dprBase + 0x000c), 0x000f0000);
  249. /* set rop2 to copypen */
  250. val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
  251. out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
  252. /* set clip rect */
  253. out32r ((pGD->dprBase + 0x002c), 0);
  254. out32r ((pGD->dprBase + 0x0030),
  255. ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
  256. /* src row pitch */
  257. val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
  258. out32r ((pGD->dprBase + 0x0010),
  259. (val | pGD->plnSizeX * pGD->gdfBytesPP));
  260. /* dst row pitch */
  261. val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
  262. out32r ((pGD->dprBase + 0x0010),
  263. (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
  264. /* window width src/dst */
  265. out32r ((pGD->dprBase + 0x003c),
  266. (((pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)<<16) |
  267. (pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)));
  268. out16r ((pGD->dprBase + 0x001e), 0x0000);
  269. /* src base adrs */
  270. out32r ((pGD->dprBase + 0x0040),
  271. (((pGD->frameAdrs/8) & 0x000fffff)));
  272. /* dst base adrs */
  273. out32r ((pGD->dprBase + 0x0044),
  274. (((pGD->frameAdrs/8) & 0x000fffff)));
  275. /* foreground color */
  276. out32r ((pGD->dprBase + 0x0014), pGD->fg);
  277. /* background color */
  278. out32r ((pGD->dprBase + 0x0018), pGD->bg);
  279. /* xcolor */
  280. out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
  281. /* xcolor mask */
  282. out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
  283. /* bit mask */
  284. out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
  285. /* load mono pattern */
  286. out32r ((pGD->dprBase + 0x0034), 0);
  287. out32r ((pGD->dprBase + 0x0038), 0);
  288. }
  289. static struct pci_device_id supported[] = {
  290. { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_710 },
  291. { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_712 },
  292. { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_810 },
  293. { }
  294. };
  295. /*****************************************************************************/
  296. static void smiLoadMsr (struct ctfb_res_modes *mode)
  297. {
  298. unsigned char h_synch_high, v_synch_high;
  299. register GraphicDevice *pGD = (GraphicDevice *)&smi;
  300. h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40; /* horizontal Synch High active */
  301. v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */
  302. out8 (SMI_MISC_REG, (h_synch_high | v_synch_high | 0x29));
  303. /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01
  304. * Selects the upper 64KB page.Bit5=1
  305. * CLK2 (left reserved in standard VGA) Bit3|2=1|0
  306. * Disables CPU access to frame buffer. Bit1=0
  307. * Sets the I/O address decode for ST01, FCR, and all CR registers
  308. * to the 3Dx I/O address range (CGA emulation). Bit0=1
  309. */
  310. }
  311. /*****************************************************************************/
  312. static void smiLoadCrt (struct ctfb_res_modes *var, int bits_per_pixel)
  313. {
  314. unsigned char cr[0x7a];
  315. int i;
  316. unsigned int hd, hs, he, ht, hbs, hbe; /* Horizontal. */
  317. unsigned int vd, vs, ve, vt, vbs, vbe; /* vertical */
  318. unsigned int bpp, wd, dblscan, interlaced;
  319. const int LineCompare = 0x3ff;
  320. unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor */
  321. register GraphicDevice *pGD = (GraphicDevice *)&smi;
  322. /* Horizontal */
  323. hd = (var->xres) / 8; /* HDisp. */
  324. hs = (var->xres + var->right_margin) / 8; /* HsStrt */
  325. he = (var->xres + var->right_margin + var->hsync_len) / 8; /* HsEnd */
  326. ht = (var->left_margin + var->xres + var->right_margin + var->hsync_len) / 8; /* HTotal */
  327. /* Blank */
  328. hbs = hd;
  329. hbe = 0; /* Blank end at 0 */
  330. /* Vertical */
  331. vd = var->yres; /* VDisplay */
  332. vs = var->yres + var->lower_margin; /* VSyncStart */
  333. ve = var->yres + var->lower_margin + var->vsync_len; /* VSyncEnd */
  334. vt = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; /* VTotal */
  335. vbs = vd;
  336. vbe = 0;
  337. bpp = bits_per_pixel;
  338. dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
  339. interlaced = var->vmode & FB_VMODE_INTERLACED;
  340. if (bpp == 15)
  341. bpp = 16;
  342. wd = var->xres * bpp / 64; /* double words per line */
  343. if (interlaced) { /* we divide all vertical timings, exept vd */
  344. vs >>= 1;
  345. vbs >>= 1;
  346. ve >>= 1;
  347. vt >>= 1;
  348. }
  349. memset (cr, 0, sizeof (cr));
  350. cr[0x00] = ht - 5;
  351. cr[0x01] = hd - 1;
  352. cr[0x02] = hbs - 1;
  353. cr[0x03] = (hbe & 0x1F);
  354. cr[0x04] = hs;
  355. cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
  356. cr[0x06] = (vt - 2) & 0xFF;
  357. cr[0x07] = (((vt - 2) & 0x100) >> 8)
  358. | (((vd - 1) & 0x100) >> 7)
  359. | ((vs & 0x100) >> 6)
  360. | (((vbs - 1) & 0x100) >> 5)
  361. | ((LineCompare & 0x100) >> 4)
  362. | (((vt - 2) & 0x200) >> 4)
  363. | (((vd - 1) & 0x200) >> 3)
  364. | ((vs & 0x200) >> 2);
  365. cr[0x30] = ((vt - 2) & 0x400) >> 7
  366. | (((vd - 1) & 0x400) >> 8)
  367. | (((vbs - 1) & 0x400) >> 9)
  368. | ((vs & 0x400) >> 10)
  369. | (interlaced) ? 0x80 : 0;
  370. cr[0x08] = 0x00;
  371. cr[0x09] = (dblscan << 7)
  372. | ((LineCompare & 0x200) >> 3)
  373. | (((vbs - 1) & 0x200) >> 4)
  374. | (TextScanLines - 1);
  375. cr[0x10] = vs & 0xff; /* VSyncPulseStart */
  376. cr[0x11] = (ve & 0x0f);
  377. cr[0x12] = (vd - 1) & 0xff; /* LineCount */
  378. cr[0x13] = wd & 0xff;
  379. cr[0x14] = 0x40;
  380. cr[0x15] = (vbs - 1) & 0xff;
  381. cr[0x16] = vbe & 0xff;
  382. cr[0x17] = 0xe3; /* but it does not work */
  383. cr[0x18] = 0xff & LineCompare;
  384. cr[0x22] = 0x00; /* todo? */
  385. /* now set the registers */
  386. for (i = 0; i <= 0x18; i++) { /*CR00 .. CR18 */
  387. smiWrite (SMI_INDX_D4, i, cr[i]);
  388. }
  389. i = 0x22; /*CR22 */
  390. smiWrite (SMI_INDX_D4, i, cr[i]);
  391. i = 0x30; /*CR30 */
  392. smiWrite (SMI_INDX_D4, i, cr[i]);
  393. }
  394. /*****************************************************************************/
  395. #define REF_FREQ 14318180
  396. #define PMIN 1
  397. #define PMAX 255
  398. #define QMIN 1
  399. #define QMAX 63
  400. static unsigned int FindPQ (unsigned int freq, unsigned int *pp, unsigned int *pq)
  401. {
  402. unsigned int n = QMIN, m = 0;
  403. long long int L = 0, P = freq, Q = REF_FREQ, H = P >> 1;
  404. long long int D = 0x7ffffffffffffffLL;
  405. for (n = QMIN; n <= QMAX; n++) {
  406. m = PMIN; /* p/q ~ freq/ref -> p*ref-freq*q ~ 0 */
  407. L = P * n - m * Q;
  408. while (L > 0 && m < PMAX) {
  409. L -= REF_FREQ; /* difference is greater as 0 subtract fref */
  410. m++; /* and increment m */
  411. }
  412. /* difference is less or equal than 0 or m > maximum */
  413. if (m > PMAX)
  414. break; /* no solution: if we increase n we get the same situation */
  415. /* L is <= 0 now */
  416. if (-L > H && m > PMIN) { /* if difference > the half fref */
  417. L += REF_FREQ; /* we take the situation before */
  418. m--; /* because its closer to 0 */
  419. }
  420. L = (L < 0) ? -L : +L; /* absolute value */
  421. if (D < L) /* if last difference was better take next n */
  422. continue;
  423. D = L;
  424. *pp = m;
  425. *pq = n; /* keep improved data */
  426. if (D == 0)
  427. break; /* best result we can get */
  428. }
  429. return (unsigned int) (0xffffffff & D);
  430. }
  431. /*****************************************************************************/
  432. static void smiLoadCcr (struct ctfb_res_modes *var, unsigned short device_id)
  433. {
  434. unsigned int p = 0;
  435. unsigned int q = 0;
  436. long long freq;
  437. register GraphicDevice *pGD = (GraphicDevice *)&smi;
  438. smiWrite (SMI_INDX_C4, 0x65, 0);
  439. smiWrite (SMI_INDX_C4, 0x66, 0);
  440. smiWrite (SMI_INDX_C4, 0x68, 0x50);
  441. if (device_id == PCI_DEVICE_ID_SMI_810) {
  442. smiWrite (SMI_INDX_C4, 0x69, 0x3);
  443. } else {
  444. smiWrite (SMI_INDX_C4, 0x69, 0x0);
  445. }
  446. /* Memory clock */
  447. switch (device_id) {
  448. case PCI_DEVICE_ID_SMI_710 :
  449. smiWrite (SMI_INDX_C4, 0x6a, 0x75);
  450. break;
  451. case PCI_DEVICE_ID_SMI_712 :
  452. smiWrite (SMI_INDX_C4, 0x6a, 0x80);
  453. break;
  454. default :
  455. smiWrite (SMI_INDX_C4, 0x6a, 0x53);
  456. break;
  457. }
  458. smiWrite (SMI_INDX_C4, 0x6b, 0x15);
  459. /* VCLK */
  460. freq = 1000000000000LL / var -> pixclock;
  461. FindPQ ((unsigned int)freq, &p, &q);
  462. smiWrite (SMI_INDX_C4, 0x6c, p);
  463. smiWrite (SMI_INDX_C4, 0x6d, q);
  464. }
  465. /*******************************************************************************
  466. *
  467. * Init video chip with common Linux graphic modes (lilo)
  468. */
  469. void *video_hw_init (void)
  470. {
  471. GraphicDevice *pGD = (GraphicDevice *)&smi;
  472. unsigned short device_id;
  473. pci_dev_t devbusfn;
  474. int videomode;
  475. unsigned long t1, hsynch, vsynch;
  476. unsigned int pci_mem_base, *vm;
  477. char *penv;
  478. int tmp, i, bits_per_pixel;
  479. struct ctfb_res_modes *res_mode;
  480. struct ctfb_res_modes var_mode;
  481. unsigned char videoout;
  482. /* Search for video chip */
  483. printf("Video: ");
  484. if ((devbusfn = pci_find_devices(supported, 0)) < 0)
  485. {
  486. printf ("Controller not found !\n");
  487. return (NULL);
  488. }
  489. /* PCI setup */
  490. pci_write_config_dword (devbusfn, PCI_COMMAND, (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
  491. pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
  492. pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
  493. pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
  494. tmp = 0;
  495. videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE;
  496. /* get video mode via environment */
  497. if ((penv = getenv ("videomode")) != NULL) {
  498. /* deceide if it is a string */
  499. if (penv[0] <= '9') {
  500. videomode = (int) simple_strtoul (penv, NULL, 16);
  501. tmp = 1;
  502. }
  503. } else {
  504. tmp = 1;
  505. }
  506. if (tmp) {
  507. /* parameter are vesa modes */
  508. /* search params */
  509. for (i = 0; i < VESA_MODES_COUNT; i++) {
  510. if (vesa_modes[i].vesanr == videomode)
  511. break;
  512. }
  513. if (i == VESA_MODES_COUNT) {
  514. printf ("no VESA Mode found, switching to mode 0x%x ", CONFIG_SYS_DEFAULT_VIDEO_MODE);
  515. i = 0;
  516. }
  517. res_mode =
  518. (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
  519. resindex];
  520. bits_per_pixel = vesa_modes[i].bits_per_pixel;
  521. } else {
  522. res_mode = (struct ctfb_res_modes *) &var_mode;
  523. bits_per_pixel = video_get_params (res_mode, penv);
  524. }
  525. /* calculate hsynch and vsynch freq (info only) */
  526. t1 = (res_mode->left_margin + res_mode->xres +
  527. res_mode->right_margin + res_mode->hsync_len) / 8;
  528. t1 *= 8;
  529. t1 *= res_mode->pixclock;
  530. t1 /= 1000;
  531. hsynch = 1000000000L / t1;
  532. t1 *=
  533. (res_mode->upper_margin + res_mode->yres +
  534. res_mode->lower_margin + res_mode->vsync_len);
  535. t1 /= 1000;
  536. vsynch = 1000000000L / t1;
  537. /* fill in Graphic device struct */
  538. sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
  539. res_mode->yres, bits_per_pixel, (hsynch / 1000),
  540. (vsynch / 1000));
  541. printf ("%s\n", pGD->modeIdent);
  542. pGD->winSizeX = res_mode->xres;
  543. pGD->winSizeY = res_mode->yres;
  544. pGD->plnSizeX = res_mode->xres;
  545. pGD->plnSizeY = res_mode->yres;
  546. switch (bits_per_pixel) {
  547. case 8:
  548. pGD->gdfBytesPP = 1;
  549. pGD->gdfIndex = GDF__8BIT_INDEX;
  550. break;
  551. case 15:
  552. pGD->gdfBytesPP = 2;
  553. pGD->gdfIndex = GDF_15BIT_555RGB;
  554. break;
  555. case 16:
  556. pGD->gdfBytesPP = 2;
  557. pGD->gdfIndex = GDF_16BIT_565RGB;
  558. break;
  559. case 24:
  560. pGD->gdfBytesPP = 3;
  561. pGD->gdfIndex = GDF_24BIT_888RGB;
  562. break;
  563. }
  564. pGD->isaBase = CONFIG_SYS_ISA_IO;
  565. pGD->pciBase = pci_mem_base;
  566. pGD->dprBase = (pci_mem_base + 0x400000 + 0x8000);
  567. pGD->vprBase = (pci_mem_base + 0x400000 + 0xc000);
  568. pGD->cprBase = (pci_mem_base + 0x400000 + 0xe000);
  569. pGD->frameAdrs = pci_mem_base;
  570. pGD->memSize = VIDEO_MEM_SIZE;
  571. /* Set up hardware : select color mode,
  572. set Register base to isa 3dx for 3?x regs*/
  573. out8 (SMI_MISC_REG, 0x01);
  574. /* Turn off display */
  575. smiWrite (SMI_INDX_C4, 0x01, 0x20);
  576. /* Unlock ext. crt regs */
  577. out8 (SMI_LOCK_REG, 0x40);
  578. /* Unlock crt regs 0-7 */
  579. smiWrite (SMI_INDX_D4, 0x11, 0x0e);
  580. /* Sytem Control Register */
  581. smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SCR, sizeof(SMI_SCR));
  582. /* extented CRT Register */
  583. smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5, SMI_EXT_CRT, sizeof(SMI_EXT_CRT));
  584. /* Attributes controller registers */
  585. smiLoadRegs (SMI_INDX_ATTR, SMI_INDX_ATTR, SMI_ATTR, sizeof(SMI_ATTR));
  586. /* Graphics Controller Register */
  587. smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF, SMI_GCR, sizeof(SMI_GCR));
  588. /* Sequencer Register */
  589. smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SEQR, sizeof(SMI_SEQR));
  590. /* Power Control Register */
  591. smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_PCR, sizeof(SMI_PCR));
  592. /* Memory Control Register */
  593. /* Register MSR62 is a power on configurable register. We don't */
  594. /* modify it */
  595. smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_MCR, sizeof(SMI_MCR));
  596. /* Set misc output register */
  597. smiLoadMsr (res_mode);
  598. /* Set CRT and Clock control registers */
  599. smiLoadCrt (res_mode, bits_per_pixel);
  600. smiLoadCcr (res_mode, device_id);
  601. /* Hardware Cusor Register */
  602. smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_HCR, sizeof(SMI_HCR));
  603. /* Enable Display */
  604. videoout = 2; /* Default output is CRT */
  605. if ((penv = getenv ("videoout")) != NULL) {
  606. /* deceide if it is a string */
  607. videoout = (int) simple_strtoul (penv, NULL, 16);
  608. }
  609. smiWrite (SMI_INDX_C4, 0x31, videoout);
  610. /* Video processor default setup */
  611. smiInitVideoProcessor ();
  612. /* Capture port default setup */
  613. smiInitCapturePort ();
  614. /* Drawing engine default setup */
  615. smiInitDrawingEngine ();
  616. /* Turn on display */
  617. smiWrite (0x3c4, 0x01, 0x01);
  618. /* Clear video memory */
  619. i = pGD->memSize/4;
  620. vm = (unsigned int *)pGD->pciBase;
  621. while(i--)
  622. *vm++ = 0;
  623. return ((void*)&smi);
  624. }
  625. /*******************************************************************************
  626. *
  627. * Drawing engine fill on screen region
  628. */
  629. void video_hw_rectfill (
  630. unsigned int bpp, /* bytes per pixel */
  631. unsigned int dst_x, /* dest pos x */
  632. unsigned int dst_y, /* dest pos y */
  633. unsigned int dim_x, /* frame width */
  634. unsigned int dim_y, /* frame height */
  635. unsigned int color /* fill color */
  636. )
  637. {
  638. register GraphicDevice *pGD = (GraphicDevice *)&smi;
  639. register unsigned int control;
  640. dim_x *= bpp;
  641. out32r ((pGD->dprBase + 0x0014), color);
  642. out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
  643. out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
  644. control = 0x0000ffff & in32r ((pGD->dprBase + 0x000c));
  645. control |= 0x80010000;
  646. out32r ((pGD->dprBase + 0x000c), control);
  647. /* Wait for drawing processor */
  648. do
  649. {
  650. out8 ((pGD->isaBase + 0x3c4), 0x16);
  651. } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
  652. }
  653. /*******************************************************************************
  654. *
  655. * Drawing engine bitblt with screen region
  656. */
  657. void video_hw_bitblt (
  658. unsigned int bpp, /* bytes per pixel */
  659. unsigned int src_x, /* source pos x */
  660. unsigned int src_y, /* source pos y */
  661. unsigned int dst_x, /* dest pos x */
  662. unsigned int dst_y, /* dest pos y */
  663. unsigned int dim_x, /* frame width */
  664. unsigned int dim_y /* frame height */
  665. )
  666. {
  667. register GraphicDevice *pGD = (GraphicDevice *)&smi;
  668. register unsigned int control;
  669. dim_x *= bpp;
  670. if ((src_y<dst_y) || ((src_y==dst_y) && (src_x<dst_x)))
  671. {
  672. out32r ((pGD->dprBase + 0x0000), (((src_x+dim_x-1)<<16) | (src_y+dim_y-1)));
  673. out32r ((pGD->dprBase + 0x0004), (((dst_x+dim_x-1)<<16) | (dst_y+dim_y-1)));
  674. control = 0x88000000;
  675. } else {
  676. out32r ((pGD->dprBase + 0x0000), ((src_x<<16) | src_y));
  677. out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
  678. control = 0x80000000;
  679. }
  680. out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
  681. control |= (0x0000ffff & in32r ((pGD->dprBase + 0x000c)));
  682. out32r ((pGD->dprBase + 0x000c), control);
  683. /* Wait for drawing processor */
  684. do
  685. {
  686. out8 ((pGD->isaBase + 0x3c4), 0x16);
  687. } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
  688. }
  689. /*******************************************************************************
  690. *
  691. * Set a RGB color in the LUT (8 bit index)
  692. */
  693. void video_set_lut (
  694. unsigned int index, /* color number */
  695. unsigned char r, /* red */
  696. unsigned char g, /* green */
  697. unsigned char b /* blue */
  698. )
  699. {
  700. register GraphicDevice *pGD = (GraphicDevice *)&smi;
  701. out8 (SMI_LUT_MASK, 0xff);
  702. out8 (SMI_LUT_START, (char)index);
  703. out8 (SMI_LUT_RGB, r>>2); /* red */
  704. udelay (10);
  705. out8 (SMI_LUT_RGB, g>>2); /* green */
  706. udelay (10);
  707. out8 (SMI_LUT_RGB, b>>2); /* blue */
  708. udelay (10);
  709. }