smiLynxEM.c 24 KB

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