smiLynxEM.c 24 KB

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