matroxfb_misc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:28k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *
  3.  * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
  4.  *
  5.  * (c) 1998,1999,2000,2001 Petr Vandrovec <vandrove@vc.cvut.cz>
  6.  *
  7.  * Portions Copyright (c) 2001 Matrox Graphics Inc.
  8.  *
  9.  * Version: 1.62 2001/11/29
  10.  *
  11.  * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
  12.  *
  13.  * Contributors: "menion?" <menion@mindless.com>
  14.  *                     Betatesting, fixes, ideas
  15.  *
  16.  *               "Kurt Garloff" <garloff@suse.de>
  17.  *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
  18.  *
  19.  *               "Tom Rini" <trini@kernel.crashing.org>
  20.  *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
  21.  *
  22.  *               "Bibek Sahu" <scorpio@dodds.net>
  23.  *                     Access device through readb|w|l and write b|w|l
  24.  *                     Extensive debugging stuff
  25.  *
  26.  *               "Daniel Haun" <haund@usa.net>
  27.  *                     Testing, hardware cursor fixes
  28.  *
  29.  *               "Scott Wood" <sawst46+@pitt.edu>
  30.  *                     Fixes
  31.  *
  32.  *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
  33.  *                     Betatesting
  34.  *
  35.  *               "Kelly French" <targon@hazmat.com>
  36.  *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
  37.  *                     Betatesting, bug reporting
  38.  *
  39.  *               "Pablo Bianucci" <pbian@pccp.com.ar>
  40.  *                     Fixes, ideas, betatesting
  41.  *
  42.  *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
  43.  *                     Fixes, enhandcements, ideas, betatesting
  44.  *
  45.  *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
  46.  *                     PPC betatesting, PPC support, backward compatibility
  47.  *
  48.  *               "Paul Womar" <Paul@pwomar.demon.co.uk>
  49.  *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
  50.  *                     PPC betatesting
  51.  *
  52.  *               "Thomas Pornin" <pornin@bolet.ens.fr>
  53.  *                     Alpha betatesting
  54.  *
  55.  *               "Pieter van Leuven" <pvl@iae.nl>
  56.  *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
  57.  *                     G100 testing
  58.  *
  59.  *               "H. Peter Arvin" <hpa@transmeta.com>
  60.  *                     Ideas
  61.  *
  62.  *               "Cort Dougan" <cort@cs.nmt.edu>
  63.  *                     CHRP fixes and PReP cleanup
  64.  *
  65.  *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
  66.  *                     G400 support
  67.  *
  68.  *               "David C. Hansen" <haveblue@us.ibm.com>
  69.  *                     Fixes
  70.  *
  71.  * (following author is not in any relation with this code, but his code
  72.  *  is included in this driver)
  73.  *
  74.  * Based on framebuffer driver for VBE 2.0 compliant graphic boards
  75.  *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
  76.  *
  77.  * (following author is not in any relation with this code, but his ideas
  78.  *  were used when writting this driver)
  79.  *
  80.  *  FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
  81.  *
  82.  */
  83. /* make checkconfig does not check includes for this... */
  84. #include <linux/config.h>
  85. #include "matroxfb_misc.h"
  86. #include <linux/interrupt.h>
  87. #include <linux/matroxfb.h>
  88. void matroxfb_createcursorshape(WPMINFO struct display* p, int vmode) {
  89. unsigned int h;
  90. unsigned int cu, cd;
  91. h = fontheight(p);
  92. if (vmode & FB_VMODE_DOUBLE)
  93. h *= 2;
  94. cd = h;
  95. if (cd >= 10)
  96. cd--;
  97. switch (ACCESS_FBINFO(cursor.type) = (p->conp->vc_cursor_type & CUR_HWMASK)) {
  98. case CUR_NONE:
  99. cu = cd;
  100. break;
  101. case CUR_UNDERLINE:
  102. cu = cd - 2;
  103. break;
  104. case CUR_LOWER_THIRD:
  105. cu = (h * 2) / 3;
  106. break;
  107. case CUR_LOWER_HALF:
  108. cu = h / 2;
  109. break;
  110. case CUR_TWO_THIRDS:
  111. cu = h / 3;
  112. break;
  113. case CUR_BLOCK:
  114. default:
  115. cu = 0;
  116. cd = h;
  117. break;
  118. }
  119. ACCESS_FBINFO(cursor.w) = fontwidth(p);
  120. ACCESS_FBINFO(cursor.u) = cu;
  121. ACCESS_FBINFO(cursor.d) = cd;
  122. }
  123. void matroxfb_DAC_out(CPMINFO int reg, int val) {
  124. DBG_REG("outDAC");
  125. mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
  126. mga_outb(M_RAMDAC_BASE+M_X_DATAREG, val);
  127. }
  128. int matroxfb_DAC_in(CPMINFO int reg) {
  129. DBG_REG("inDAC");
  130. mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
  131. return mga_inb(M_RAMDAC_BASE+M_X_DATAREG);
  132. }
  133. void matroxfb_var2my(struct fb_var_screeninfo* var, struct my_timming* mt) {
  134. unsigned int pixclock = var->pixclock;
  135. DBG("var2my")
  136. if (!pixclock) pixclock = 10000; /* 10ns = 100MHz */
  137. mt->pixclock = 1000000000 / pixclock;
  138. if (mt->pixclock < 1) mt->pixclock = 1;
  139. mt->dblscan = var->vmode & FB_VMODE_DOUBLE;
  140. mt->interlaced = var->vmode & FB_VMODE_INTERLACED;
  141. mt->HDisplay = var->xres;
  142. mt->HSyncStart = mt->HDisplay + var->right_margin;
  143. mt->HSyncEnd = mt->HSyncStart + var->hsync_len;
  144. mt->HTotal = mt->HSyncEnd + var->left_margin;
  145. mt->VDisplay = var->yres;
  146. mt->VSyncStart = mt->VDisplay + var->lower_margin;
  147. mt->VSyncEnd = mt->VSyncStart + var->vsync_len;
  148. mt->VTotal = mt->VSyncEnd + var->upper_margin;
  149. mt->sync = var->sync;
  150. }
  151. int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int freq, unsigned int fmax,
  152. unsigned int* in, unsigned int* feed, unsigned int* post) {
  153. unsigned int bestdiff = ~0;
  154. unsigned int bestvco = 0;
  155. unsigned int fxtal = pll->ref_freq;
  156. unsigned int fwant;
  157. unsigned int p;
  158. DBG("PLL_calcclock")
  159. fwant = freq;
  160. #ifdef DEBUG
  161. printk(KERN_ERR "post_shift_max: %dn", pll->post_shift_max);
  162. printk(KERN_ERR "ref_freq: %dn", pll->ref_freq);
  163. printk(KERN_ERR "freq: %dn", freq);
  164. printk(KERN_ERR "vco_freq_min: %dn", pll->vco_freq_min);
  165. printk(KERN_ERR "in_div_min: %dn", pll->in_div_min);
  166. printk(KERN_ERR "in_div_max: %dn", pll->in_div_max);
  167. printk(KERN_ERR "feed_div_min: %dn", pll->feed_div_min);
  168. printk(KERN_ERR "feed_div_max: %dn", pll->feed_div_max);
  169. printk(KERN_ERR "fmax: %dn", fmax);
  170. #endif
  171. for (p = 1; p <= pll->post_shift_max; p++) {
  172. if (fwant * 2 > fmax)
  173. break;
  174. fwant *= 2;
  175. }
  176. if (fwant < pll->vco_freq_min) fwant = pll->vco_freq_min;
  177. if (fwant > fmax) fwant = fmax;
  178. for (; p-- > 0; fwant >>= 1, bestdiff >>= 1) {
  179. unsigned int m;
  180. if (fwant < pll->vco_freq_min) break;
  181. for (m = pll->in_div_min; m <= pll->in_div_max; m++) {
  182. unsigned int diff, fvco;
  183. unsigned int n;
  184. n = (fwant * (m + 1) + (fxtal >> 1)) / fxtal - 1;
  185. if (n > pll->feed_div_max)
  186. break;
  187. if (n < pll->feed_div_min)
  188. n = pll->feed_div_min;
  189. fvco = (fxtal * (n + 1)) / (m + 1);
  190. if (fvco < fwant)
  191. diff = fwant - fvco;
  192. else
  193. diff = fvco - fwant;
  194. if (diff < bestdiff) {
  195. bestdiff = diff;
  196. *post = p;
  197. *in = m;
  198. *feed = n;
  199. bestvco = fvco;
  200. }
  201. }
  202. }
  203. dprintk(KERN_ERR "clk: %02X %02X %02X %d %d %dn", *in, *feed, *post, fxtal, bestvco, fwant);
  204. return bestvco;
  205. }
  206. int matroxfb_vgaHWinit(WPMINFO struct my_timming* m, struct display* p) {
  207. unsigned int hd, hs, he, hbe, ht;
  208. unsigned int vd, vs, ve, vt;
  209. unsigned int wd;
  210. unsigned int divider;
  211. int i;
  212. int text = p->type == FB_TYPE_TEXT;
  213. int fwidth;
  214. struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw);
  215. if (text) {
  216. fwidth = fontwidth(p);
  217. if (!fwidth) fwidth = 8;
  218. } else
  219. fwidth = 8;
  220. DBG("vgaHWinit")
  221. hw->SEQ[0] = 0x00;
  222. if (fwidth == 9)
  223. hw->SEQ[1] = 0x00;
  224. else
  225. hw->SEQ[1] = 0x01; /* or 0x09 */
  226. hw->SEQ[2] = 0x0F; /* bitplanes */
  227. hw->SEQ[3] = 0x00;
  228. if (text)
  229. hw->SEQ[4] = 0x02;
  230. else
  231. hw->SEQ[4] = 0x0E;
  232. /* CRTC 0..7, 9, 16..19, 21, 22 are reprogrammed by Matrox Millennium code... Hope that by MGA1064 too */
  233. if (m->dblscan) {
  234. m->VTotal <<= 1;
  235. m->VDisplay <<= 1;
  236. m->VSyncStart <<= 1;
  237. m->VSyncEnd <<= 1;
  238. }
  239. if (m->interlaced) {
  240. m->VTotal >>= 1;
  241. m->VDisplay >>= 1;
  242. m->VSyncStart >>= 1;
  243. m->VSyncEnd >>= 1;
  244. }
  245. /* GCTL is ignored when not using 0xA0000 aperture */
  246. hw->GCTL[0] = 0x00;
  247. hw->GCTL[1] = 0x00;
  248. hw->GCTL[2] = 0x00;
  249. hw->GCTL[3] = 0x00;
  250. hw->GCTL[4] = 0x00;
  251. if (text) {
  252. hw->GCTL[5] = 0x10;
  253. hw->GCTL[6] = 0x02;
  254. } else {
  255. hw->GCTL[5] = 0x40;
  256. hw->GCTL[6] = 0x05;
  257. }
  258. hw->GCTL[7] = 0x0F;
  259. hw->GCTL[8] = 0xFF;
  260. /* Whole ATTR is ignored in PowerGraphics mode */
  261. for (i = 0; i < 16; i++)
  262. hw->ATTR[i] = i;
  263. if (text) {
  264. hw->ATTR[16] = 0x04;
  265. } else {
  266. hw->ATTR[16] = 0x41;
  267. }
  268. hw->ATTR[17] = 0xFF;
  269. hw->ATTR[18] = 0x0F;
  270. if (fwidth == 9)
  271. hw->ATTR[19] = 0x08;
  272. else
  273. hw->ATTR[19] = 0x00;
  274. hw->ATTR[20] = 0x00;
  275. if (text) {
  276. hd = m->HDisplay / fwidth;
  277. hs = m->HSyncStart / fwidth;
  278. he = m->HSyncEnd / fwidth;
  279. ht = m->HTotal / fwidth;
  280. divider = 8;
  281. } else {
  282. hd = m->HDisplay >> 3;
  283. hs = m->HSyncStart >> 3;
  284. he = m->HSyncEnd >> 3;
  285. ht = m->HTotal >> 3;
  286. /* standard timmings are in 8pixels, but for interleaved we cannot */
  287. /* do it for 4bpp (because of (4bpp >> 1(interleaved))/4 == 0) */
  288. /* using 16 or more pixels per unit can save us */
  289. divider = ACCESS_FBINFO(curr.final_bppShift);
  290. }
  291. while (divider & 3) {
  292. hd >>= 1;
  293. hs >>= 1;
  294. he >>= 1;
  295. ht >>= 1;
  296. divider <<= 1;
  297. }
  298. divider = divider / 4;
  299. /* divider can be from 1 to 8 */
  300. while (divider > 8) {
  301. hd <<= 1;
  302. hs <<= 1;
  303. he <<= 1;
  304. ht <<= 1;
  305. divider >>= 1;
  306. }
  307. hd = hd - 1;
  308. hs = hs - 1;
  309. he = he - 1;
  310. ht = ht - 1;
  311. vd = m->VDisplay - 1;
  312. vs = m->VSyncStart - 1;
  313. ve = m->VSyncEnd - 1;
  314. vt = m->VTotal - 2;
  315. /* G200 cannot work with (ht & 7) == 6 */
  316. if (((ht & 0x07) == 0x06) || ((ht & 0x0F) == 0x04))
  317. ht++;
  318. if (text) {
  319. hbe = ht - 1;
  320. wd = p->var.xres_virtual / (fwidth * 2);
  321. } else {
  322. hbe = ht;
  323. wd = p->var.xres_virtual * ACCESS_FBINFO(curr.final_bppShift) / 64;
  324. }
  325. hw->CRTCEXT[0] = 0;
  326. hw->CRTCEXT[5] = 0;
  327. if (m->interlaced) {
  328. hw->CRTCEXT[0] = 0x80;
  329. hw->CRTCEXT[5] = (hs + he - ht) >> 1;
  330. if (!m->dblscan)
  331. wd <<= 1;
  332. vt &= ~1;
  333. }
  334. hw->CRTCEXT[0] |=  (wd & 0x300) >> 4;
  335. hw->CRTCEXT[1] = (((ht - 4) & 0x100) >> 8) |
  336.   ((hd      & 0x100) >> 7) | /* blanking */
  337.   ((hs      & 0x100) >> 6) | /* sync start */
  338.    (hbe     & 0x040);  /* end hor. blanking */
  339. if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY)
  340. hw->CRTCEXT[1] |= 0x88; /* enable horizontal and vertical vidrst */
  341. hw->CRTCEXT[2] =  ((vt & 0xC00) >> 10) |
  342.   ((vd & 0x400) >>  8) | /* disp end */
  343.   ((vd & 0xC00) >>  7) | /* vblanking start */
  344.   ((vs & 0xC00) >>  5);
  345. if (text)
  346. hw->CRTCEXT[3] = 0x00;
  347. else
  348. hw->CRTCEXT[3] = (divider - 1) | 0x80;
  349. hw->CRTCEXT[4] = 0;
  350. hw->CRTC[0] = ht-4;
  351. hw->CRTC[1] = hd;
  352. hw->CRTC[2] = hd;
  353. hw->CRTC[3] = (hbe & 0x1F) | 0x80;
  354. hw->CRTC[4] = hs;
  355. hw->CRTC[5] = ((hbe & 0x20) << 2) | (he & 0x1F);
  356. if (text)
  357. hw->CRTC[5] |= 0x60; /* delay sync for 3 clocks (to same picture position on MGA and VGA) */
  358. hw->CRTC[6] = vt & 0xFF;
  359. hw->CRTC[7] = ((vt & 0x100) >> 8) |
  360.       ((vd & 0x100) >> 7) |
  361.       ((vs & 0x100) >> 6) |
  362.       ((vd & 0x100) >> 5) |
  363.       0x10                |
  364.       ((vt & 0x200) >> 4) |
  365.       ((vd & 0x200) >> 3) |
  366.       ((vs & 0x200) >> 2);
  367. hw->CRTC[8] = 0x00;
  368. hw->CRTC[9] = ((vd & 0x200) >> 4) | 0x40;
  369. if (text)
  370. hw->CRTC[9] |= fontheight(p) - 1;
  371. if (m->dblscan && !m->interlaced)
  372. hw->CRTC[9] |= 0x80;
  373. for (i = 10; i < 16; i++)
  374. hw->CRTC[i] = 0x00;
  375. hw->CRTC[16] = vs /* & 0xFF */;
  376. hw->CRTC[17] = (ve & 0x0F) | 0x20;
  377. hw->CRTC[18] = vd /* & 0xFF */;
  378. hw->CRTC[19] = wd /* & 0xFF */;
  379. hw->CRTC[20] = 0x00;
  380. hw->CRTC[21] = vd /* & 0xFF */;
  381. hw->CRTC[22] = (vt + 1) /* & 0xFF */;
  382. if (text) {
  383. if (ACCESS_FBINFO(devflags.textmode) == 1)
  384. hw->CRTC[23] = 0xC3;
  385. else
  386. hw->CRTC[23] = 0xA3;
  387. if (ACCESS_FBINFO(devflags.textmode) == 4)
  388. hw->CRTC[20] = 0x5F;
  389. else
  390. hw->CRTC[20] = 0x1F;
  391. } else
  392. hw->CRTC[23] = 0xC3;
  393. hw->CRTC[24] = 0xFF;
  394. return 0;
  395. };
  396. void matroxfb_vgaHWrestore(WPMINFO2) {
  397. int i;
  398. struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw);
  399. CRITFLAGS
  400. DBG("vgaHWrestore")
  401. dprintk(KERN_INFO "MiscOutReg: %02Xn", hw->MiscOutReg);
  402. dprintk(KERN_INFO "SEQ regs:   ");
  403. for (i = 0; i < 5; i++)
  404. dprintk("%02X:", hw->SEQ[i]);
  405. dprintk("n");
  406. dprintk(KERN_INFO "GDC regs:   ");
  407. for (i = 0; i < 9; i++)
  408. dprintk("%02X:", hw->GCTL[i]);
  409. dprintk("n");
  410. dprintk(KERN_INFO "CRTC regs: ");
  411. for (i = 0; i < 25; i++)
  412. dprintk("%02X:", hw->CRTC[i]);
  413. dprintk("n");
  414. dprintk(KERN_INFO "ATTR regs: ");
  415. for (i = 0; i < 21; i++)
  416. dprintk("%02X:", hw->ATTR[i]);
  417. dprintk("n");
  418. CRITBEGIN
  419. mga_inb(M_ATTR_RESET);
  420. mga_outb(M_ATTR_INDEX, 0);
  421. mga_outb(M_MISC_REG, hw->MiscOutReg);
  422. for (i = 1; i < 5; i++)
  423. mga_setr(M_SEQ_INDEX, i, hw->SEQ[i]);
  424. mga_setr(M_CRTC_INDEX, 17, hw->CRTC[17] & 0x7F);
  425. for (i = 0; i < 25; i++)
  426. mga_setr(M_CRTC_INDEX, i, hw->CRTC[i]);
  427. for (i = 0; i < 9; i++)
  428. mga_setr(M_GRAPHICS_INDEX, i, hw->GCTL[i]);
  429. for (i = 0; i < 21; i++) {
  430. mga_inb(M_ATTR_RESET);
  431. mga_outb(M_ATTR_INDEX, i);
  432. mga_outb(M_ATTR_INDEX, hw->ATTR[i]);
  433. }
  434. mga_outb(M_PALETTE_MASK, 0xFF);
  435. mga_outb(M_DAC_REG, 0x00);
  436. for (i = 0; i < 768; i++)
  437. mga_outb(M_DAC_VAL, hw->DACpal[i]);
  438. mga_inb(M_ATTR_RESET);
  439. mga_outb(M_ATTR_INDEX, 0x20);
  440. CRITEND
  441. }
  442. void matroxfb_fastfont_init(struct matrox_fb_info* minfo){
  443. unsigned int size;
  444. size = ACCESS_FBINFO(fastfont.size);
  445. ACCESS_FBINFO(fastfont.size) = 0;
  446. if (size) {
  447. unsigned int end = ACCESS_FBINFO(video.len_usable);
  448. if (size < end) {
  449. unsigned int start;
  450. start = (end - size) & PAGE_MASK;
  451. if (start >= 0x00100000) {
  452. ACCESS_FBINFO(video.len_usable) = start;
  453. ACCESS_FBINFO(fastfont.mgabase) = start * 8;
  454. ACCESS_FBINFO(fastfont.vbase) = ACCESS_FBINFO(video.vbase);
  455. vaddr_add(&ACCESS_FBINFO(fastfont.vbase), start);
  456. ACCESS_FBINFO(fastfont.size) = end - start;
  457. }
  458. }
  459. }
  460. }
  461. #ifndef FNTCHARCNT
  462. #define FNTCHARCNT(fd) (((int *)(fd))[-3])
  463. #endif
  464. int matrox_text_loadfont(WPMINFO struct display* p) {
  465. unsigned int fsize;
  466. unsigned int width;
  467. vaddr_t dst;
  468. unsigned int i;
  469. u_int8_t* font;
  470. CRITFLAGS
  471. if (!p || !p->fontdata)
  472. return 0;
  473. width = fontwidth(p);
  474. fsize = p->userfont?FNTCHARCNT(p->fontdata):256;
  475. dst = ACCESS_FBINFO(video.vbase);
  476. i = 2;
  477. font = (u_int8_t*)p->fontdata;
  478. CRITBEGIN
  479. mga_setr(M_SEQ_INDEX, 0x02, 0x04);
  480. while (fsize--) {
  481. int l;
  482. for (l = 0; l < fontheight(p); l++) {
  483. mga_writeb(dst, i, *font++);
  484. if (fontwidth(p) > 8) font++;
  485. i += ACCESS_FBINFO(devflags.vgastep);
  486. }
  487. i += (32 - fontheight(p)) * ACCESS_FBINFO(devflags.vgastep);
  488. }
  489. mga_setr(M_SEQ_INDEX, 0x02, 0x03);
  490. CRITEND
  491. return 1;
  492. }
  493. int matroxfb_fastfont_tryset(WPMINFO struct display* p) {
  494. unsigned int fsize;
  495. unsigned int width;
  496. CRITFLAGS
  497. if (!p || !p->fontdata)
  498. return 0;
  499. width = fontwidth(p);
  500. if (width > 32)
  501. return 0;
  502. fsize = (p->userfont?FNTCHARCNT(p->fontdata):256) * fontheight(p);
  503. if (((fsize * width + 31) / 32) * 4 > ACCESS_FBINFO(fastfont.size))
  504. return 0;
  505. CRITBEGIN
  506. mga_outl(M_OPMODE, M_OPMODE_8BPP);
  507. if (width <= 8) {
  508. if (width == 8)
  509. mga_memcpy_toio(ACCESS_FBINFO(fastfont.vbase), 0, p->fontdata, fsize);
  510. else {
  511. vaddr_t dst;
  512. unsigned int i;
  513. u_int8_t* font;
  514. u_int32_t mask, valid, reg;
  515. dst = ACCESS_FBINFO(fastfont.vbase);
  516. font = (u_int8_t*)p->fontdata;
  517. mask = ~0 << (8 - width);
  518. valid = 0;
  519. reg = 0;
  520. i = 0;
  521. while (fsize--) {
  522. reg |= (*font++ & mask) << (8 - valid);
  523. valid += width;
  524. if (valid >= 8) {
  525. mga_writeb(dst, i++, reg >> 8);
  526. reg = reg << 8;
  527. valid -= 8;
  528. }
  529. }
  530. if (valid)
  531. mga_writeb(dst, i, reg >> 8);
  532. }
  533. } else if (width <= 16) {
  534. if (width == 16)
  535. mga_memcpy_toio(ACCESS_FBINFO(fastfont.vbase), 0, p->fontdata, fsize*2);
  536. else {
  537. vaddr_t dst;
  538. u_int16_t* font;
  539. u_int32_t mask, valid, reg;
  540. unsigned int i;
  541. dst = ACCESS_FBINFO(fastfont.vbase);
  542. font = (u_int16_t*)p->fontdata;
  543. mask = ~0 << (16 - width);
  544. valid = 0;
  545. reg = 0;
  546. i = 0;
  547. while (fsize--) {
  548. reg |= (ntohs(*font++) & mask) << (16 - valid);
  549. valid += width;
  550. if (valid >= 16) {
  551. mga_writew(dst, i, htons(reg >> 16));
  552. i += 2;
  553. reg = reg << 16;
  554. valid -= 16;
  555. }
  556. }
  557. if (valid)
  558. mga_writew(dst, i, htons(reg >> 16));
  559. }
  560. } else {
  561. if (width == 32)
  562. mga_memcpy_toio(ACCESS_FBINFO(fastfont.vbase), 0, p->fontdata, fsize*4);
  563. else {
  564. vaddr_t dst;
  565. u_int32_t* font;
  566. u_int32_t mask, valid, reg;
  567. unsigned int i;
  568. dst = ACCESS_FBINFO(fastfont.vbase);
  569. font = (u_int32_t*)p->fontdata;
  570. mask = ~0 << (32 - width);
  571. valid = 0;
  572. reg = 0;
  573. i = 0;
  574. while (fsize--) {
  575. reg |= (ntohl(*font) & mask) >> valid;
  576. valid += width;
  577. if (valid >= 32) {
  578. mga_writel(dst, i, htonl(reg));
  579. i += 4;
  580. valid -= 32;
  581. if (valid)
  582. reg = (ntohl(*font) & mask) << (width - valid);
  583. else
  584. reg = 0;
  585. }
  586. font++;
  587. }
  588. if (valid)
  589. mga_writel(dst, i, htonl(reg));
  590. }
  591. }
  592. mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
  593. CRITEND
  594. return 1;
  595. }
  596. static void get_pins(unsigned char* pins, struct matrox_bios* bd) {
  597. unsigned int b0 = readb(pins);
  598. if (b0 == 0x2E && readb(pins+1) == 0x41) {
  599. unsigned int pins_len = readb(pins+2);
  600. unsigned int i;
  601. unsigned char cksum;
  602. unsigned char* dst = bd->pins;
  603. if (pins_len < 3 || pins_len > 128) {
  604. return;
  605. }
  606. *dst++ = 0x2E;
  607. *dst++ = 0x41;
  608. *dst++ = pins_len;
  609. cksum = 0x2E + 0x41 + pins_len;
  610. for (i = 3; i < pins_len; i++) {
  611. cksum += *dst++ = readb(pins+i);
  612. }
  613. if (cksum) {
  614. return;
  615. }
  616. bd->pins_len = pins_len;
  617. } else if (b0 == 0x40 && readb(pins+1) == 0x00) {
  618. unsigned int i;
  619. unsigned char* dst = bd->pins;
  620. *dst++ = 0x40;
  621. *dst++ = 0;
  622. for (i = 2; i < 0x40; i++) {
  623. *dst++ = readb(pins+i);
  624. }
  625. bd->pins_len = 0x40;
  626. }
  627. }
  628. static void get_bios_version(unsigned char* vbios, struct matrox_bios* bd) {
  629. unsigned int pcir_offset;
  630. pcir_offset = readb(vbios + 24) | (readb(vbios + 25) << 8);
  631. if (pcir_offset >= 26 && pcir_offset < 0xFFE0 &&
  632.     readb(vbios + pcir_offset    ) == 'P' &&
  633.     readb(vbios + pcir_offset + 1) == 'C' &&
  634.     readb(vbios + pcir_offset + 2) == 'I' &&
  635.     readb(vbios + pcir_offset + 3) == 'R') {
  636. unsigned char h;
  637. h = readb(vbios + pcir_offset + 0x12);
  638. bd->version.vMaj = (h >> 4) & 0xF;
  639. bd->version.vMin = h & 0xF;
  640. bd->version.vRev = readb(vbios + pcir_offset + 0x13);
  641. } else {
  642. unsigned char h;
  643. h = readb(vbios + 5);
  644. bd->version.vMaj = (h >> 4) & 0xF;
  645. bd->version.vMin = h & 0xF;
  646. bd->version.vRev = 0;
  647. }
  648. }
  649. static void get_bios_output(unsigned char* vbios, struct matrox_bios* bd) {
  650. unsigned char b;
  651. b = readb(vbios + 0x7FF1);
  652. if (b == 0xFF) {
  653. b = 0;
  654. }
  655. bd->output.state = b;
  656. }
  657. static void get_bios_tvout(unsigned char* vbios, struct matrox_bios* bd) {
  658. unsigned int i;
  659. /* Check for 'IBM .*(V....TVO' string - it means TVO BIOS */
  660. bd->output.tvout = 0;
  661. if (readb(vbios + 0x1D) != 'I' ||
  662.     readb(vbios + 0x1E) != 'B' ||
  663.     readb(vbios + 0x1F) != 'M' ||
  664.     readb(vbios + 0x20) != ' ') {
  665.      return;
  666. }
  667. for (i = 0x2D; i < 0x2D + 128; i++) {
  668. unsigned char b = readb(vbios + i);
  669. if (b == '(' && readb(vbios + i + 1) == 'V') {
  670. if (readb(vbios + i + 6) == 'T' &&
  671.     readb(vbios + i + 7) == 'V' &&
  672.     readb(vbios + i + 8) == 'O') {
  673. bd->output.tvout = 1;
  674. }
  675. return;
  676. }
  677. if (b == 0)
  678. break;
  679. }
  680. }
  681. static void parse_bios(unsigned char* vbios, struct matrox_bios* bd) {
  682. unsigned int pins_offset;
  683. if (readb(vbios) != 0x55 || readb(vbios + 1) != 0xAA) {
  684. return;
  685. }
  686. bd->bios_valid = 1;
  687. get_bios_version(vbios, bd);
  688. get_bios_output(vbios, bd);
  689. get_bios_tvout(vbios, bd);
  690. pins_offset = readb(vbios + 0x7FFC) | (readb(vbios + 0x7FFD) << 8);
  691. if (pins_offset <= 0xFF80) {
  692. get_pins(vbios + pins_offset, bd);
  693. }
  694. }
  695. #define get_u16(x) (le16_to_cpu(get_unaligned((__u16*)(x))))
  696. #define get_u32(x) (le32_to_cpu(get_unaligned((__u32*)(x))))
  697. static int parse_pins1(WPMINFO const struct matrox_bios* bd) {
  698. unsigned int maxdac;
  699. switch (bd->pins[22]) {
  700. case 0: maxdac = 175000; break;
  701. case 1: maxdac = 220000; break;
  702. default: maxdac = 240000; break;
  703. }
  704. if (get_u16(bd->pins + 24)) {
  705. maxdac = get_u16(bd->pins + 24) * 10;
  706. }
  707. MINFO->limits.pixel.vcomax = maxdac;
  708. MINFO->values.pll.system = get_u16(bd->pins + 28) ? get_u16(bd->pins + 28) * 10 : 50000;
  709. /* ignore 4MB, 8MB, module clocks */
  710. MINFO->features.pll.ref_freq = 14318;
  711. MINFO->values.reg.mctlwtst = 0x00030101;
  712. return 0;
  713. }
  714. static void default_pins1(WPMINFO2) {
  715. /* Millennium */
  716. MINFO->limits.pixel.vcomax = 220000;
  717. MINFO->values.pll.system =  50000;
  718. MINFO->features.pll.ref_freq =  14318;
  719. MINFO->values.reg.mctlwtst = 0x00030101;
  720. }
  721. static int parse_pins2(WPMINFO const struct matrox_bios* bd) {
  722. MINFO->limits.pixel.vcomax =
  723. MINFO->limits.system.vcomax = (bd->pins[41] == 0xFF) ? 230000 : ((bd->pins[41] + 100) * 1000);
  724. MINFO->values.reg.mctlwtst = ((bd->pins[51] & 0x01) ? 0x00000001 : 0) |
  725.   ((bd->pins[51] & 0x02) ? 0x00000100 : 0) |
  726.   ((bd->pins[51] & 0x04) ? 0x00010000 : 0) |
  727.   ((bd->pins[51] & 0x08) ? 0x00020000 : 0);
  728. MINFO->values.pll.system = (bd->pins[43] == 0xFF) ? 50000 : ((bd->pins[43] + 100) * 1000);
  729. MINFO->features.pll.ref_freq = 14318;
  730. return 0;
  731. }
  732. static void default_pins2(WPMINFO2) {
  733. /* Millennium II, Mystique */
  734. MINFO->limits.pixel.vcomax =
  735. MINFO->limits.system.vcomax = 230000;
  736. MINFO->values.reg.mctlwtst = 0x00030101;
  737. MINFO->values.pll.system =  50000;
  738. MINFO->features.pll.ref_freq =  14318;
  739. }
  740. static int parse_pins3(WPMINFO const struct matrox_bios* bd) {
  741. MINFO->limits.pixel.vcomax =
  742. MINFO->limits.system.vcomax = (bd->pins[36] == 0xFF) ? 230000 : ((bd->pins[36] + 100) * 1000);
  743. MINFO->values.reg.mctlwtst = get_u32(bd->pins + 48) == 0xFFFFFFFF ? 0x01250A21 : get_u32(bd->pins + 48);
  744. /* memory config */
  745. MINFO->values.reg.memrdbk = ((bd->pins[57] << 21) & 0x1E000000) |
  746.   ((bd->pins[57] << 22) & 0x00C00000) |
  747.   ((bd->pins[56] <<  1) & 0x000001E0) |
  748.   ( bd->pins[56]        & 0x0000000F);
  749. MINFO->values.reg.opt = (bd->pins[54] & 7) << 10;
  750. MINFO->values.reg.opt2 = bd->pins[58] << 12;
  751. MINFO->features.pll.ref_freq = (bd->pins[52] & 0x20) ? 14318 : 27000;
  752. return 0;
  753. }
  754. static void default_pins3(WPMINFO2) {
  755. /* G100, G200 */
  756. MINFO->limits.pixel.vcomax =
  757. MINFO->limits.system.vcomax = 230000;
  758. MINFO->values.reg.mctlwtst = 0x01250A21;
  759. MINFO->values.reg.memrdbk = 0x00000000;
  760. MINFO->values.reg.opt = 0x00000C00;
  761. MINFO->values.reg.opt2 = 0x00000000;
  762. MINFO->features.pll.ref_freq =  27000;
  763. }
  764. static int parse_pins4(WPMINFO const struct matrox_bios* bd) {
  765. MINFO->limits.pixel.vcomax = (bd->pins[ 39] == 0xFF) ? 230000 : bd->pins[ 39] * 4000;
  766. MINFO->limits.system.vcomax = (bd->pins[ 38] == 0xFF) ? MINFO->limits.pixel.vcomax : bd->pins[ 38] * 4000;
  767. MINFO->values.reg.mctlwtst = get_u32(bd->pins + 71);
  768. MINFO->values.reg.memrdbk = ((bd->pins[87] << 21) & 0x1E000000) |
  769.   ((bd->pins[87] << 22) & 0x00C00000) |
  770.   ((bd->pins[86] <<  1) & 0x000001E0) |
  771.   ( bd->pins[86]        & 0x0000000F);
  772. MINFO->values.reg.opt = ((bd->pins[53] << 15) & 0x00400000) |
  773.   ((bd->pins[53] << 22) & 0x10000000) |
  774.   ((bd->pins[53] << 10) & 0x00001C00);
  775. MINFO->values.reg.opt3 = get_u32(bd->pins + 67);
  776. MINFO->values.pll.system = (bd->pins[ 65] == 0xFF) ? 200000  : bd->pins[ 65] * 4000;
  777. MINFO->features.pll.ref_freq = (bd->pins[ 92] & 0x01) ? 14318 : 27000;
  778. return 0;
  779. }
  780. static void default_pins4(WPMINFO2) {
  781. /* G400 */
  782. MINFO->limits.pixel.vcomax =
  783. MINFO->limits.system.vcomax = 252000;
  784. MINFO->values.reg.mctlwtst = 0x04A450A1;
  785. MINFO->values.reg.memrdbk = 0x000000E7;
  786. MINFO->values.reg.opt = 0x10000400;
  787. MINFO->values.reg.opt3 = 0x0190A419;
  788. MINFO->values.pll.system = 200000;
  789. MINFO->features.pll.ref_freq = 27000;
  790. }
  791. static int parse_pins5(WPMINFO const struct matrox_bios* bd) {
  792. unsigned int mult;
  793. mult = bd->pins[4]?8000:6000;
  794. MINFO->limits.pixel.vcomax = (bd->pins[ 38] == 0xFF) ? 600000 : bd->pins[ 38] * mult;
  795. MINFO->limits.system.vcomax = (bd->pins[ 36] == 0xFF) ? MINFO->limits.pixel.vcomax : bd->pins[ 39] * mult;
  796. MINFO->limits.video.vcomax = (bd->pins[ 37] == 0xFF) ? MINFO->limits.system.vcomax : bd->pins[ 37] * mult;
  797. MINFO->limits.pixel.vcomin = (bd->pins[123] == 0xFF) ? 256000 : bd->pins[123] * mult;
  798. MINFO->limits.system.vcomin = (bd->pins[121] == 0xFF) ? MINFO->limits.pixel.vcomin : bd->pins[121] * mult;
  799. MINFO->limits.video.vcomin = (bd->pins[122] == 0xFF) ? MINFO->limits.system.vcomin : bd->pins[122] * mult;
  800. MINFO->values.pll.system =
  801. MINFO->values.pll.video = (bd->pins[ 92] == 0xFF) ? 284000 : bd->pins[ 92] * 4000;
  802. MINFO->values.reg.opt = get_u32(bd->pins+ 48);
  803. MINFO->values.reg.opt2 = get_u32(bd->pins+ 52);
  804. MINFO->values.reg.opt3 = get_u32(bd->pins+ 94);
  805. MINFO->values.reg.mctlwtst = get_u32(bd->pins+ 98);
  806. MINFO->values.reg.memmisc = get_u32(bd->pins+102);
  807. MINFO->values.reg.memrdbk = get_u32(bd->pins+106);
  808. MINFO->features.pll.ref_freq = (bd->pins[110] & 0x01) ? 14318 : 27000;
  809. MINFO->values.memory.ddr = (bd->pins[114] & 0x60) == 0x20;
  810. MINFO->values.memory.dll = (bd->pins[115] & 0x02) != 0;
  811. MINFO->values.memory.emrswen = (bd->pins[115] & 0x01) != 0;
  812. MINFO->values.reg.maccess = MINFO->values.memory.emrswen ? 0x00004000 : 0x00000000;
  813. if (bd->pins[115] & 4) {
  814. MINFO->values.reg.mctlwtst_core = MINFO->values.reg.mctlwtst;
  815. } else {
  816. u_int32_t wtst_xlat[] = { 0, 1, 5, 6, 7, 5, 2, 3 };
  817. MINFO->values.reg.mctlwtst_core = (MINFO->values.reg.mctlwtst & ~7) |
  818.                                   wtst_xlat[MINFO->values.reg.mctlwtst & 7];
  819. }
  820. return 0;
  821. }
  822. static void default_pins5(WPMINFO2) {
  823. /* Mine 16MB G450 with SDRAM DDR */
  824. MINFO->limits.pixel.vcomax =
  825. MINFO->limits.system.vcomax =
  826. MINFO->limits.video.vcomax = 600000;
  827. MINFO->limits.pixel.vcomin =
  828. MINFO->limits.system.vcomin =
  829. MINFO->limits.video.vcomin = 256000;
  830. MINFO->values.pll.system =
  831. MINFO->values.pll.video = 284000;
  832. MINFO->values.reg.opt = 0x404A1160;
  833. MINFO->values.reg.opt2 = 0x0000AC00;
  834. MINFO->values.reg.opt3 = 0x0090A409;
  835. MINFO->values.reg.mctlwtst_core =
  836. MINFO->values.reg.mctlwtst = 0x0C81462B;
  837. MINFO->values.reg.memmisc = 0x80000004;
  838. MINFO->values.reg.memrdbk = 0x01001103;
  839. MINFO->features.pll.ref_freq = 27000;
  840. MINFO->values.memory.ddr = 1;
  841. MINFO->values.memory.dll = 1;
  842. MINFO->values.memory.emrswen = 1;
  843. MINFO->values.reg.maccess = 0x00004000;
  844. }
  845. static int matroxfb_set_limits(WPMINFO const struct matrox_bios* bd) {
  846. unsigned int pins_version;
  847. static const unsigned int pinslen[] = { 64, 64, 64, 128, 128 };
  848. switch (ACCESS_FBINFO(chip)) {
  849. case MGA_2064: default_pins1(PMINFO2); break;
  850. case MGA_2164:
  851. case MGA_1064:
  852. case MGA_1164: default_pins2(PMINFO2); break;
  853. case MGA_G100:
  854. case MGA_G200: default_pins3(PMINFO2); break;
  855. case MGA_G400: default_pins4(PMINFO2); break;
  856. case MGA_G450:
  857. case MGA_G550: default_pins5(PMINFO2); break;
  858. }
  859. if (!bd->bios_valid) {
  860. printk(KERN_INFO "matroxfb: Your Matrox device does not have BIOSn");
  861. return -1;
  862. }
  863. if (bd->pins_len < 64) {
  864. printk(KERN_INFO "matroxfb: BIOS on your Matrox device does not contain powerup infon");
  865. return -1;
  866. }
  867. if (bd->pins[0] == 0x2E && bd->pins[1] == 0x41) {
  868. pins_version = bd->pins[5];
  869. if (pins_version < 2 || pins_version > 5) {
  870. printk(KERN_INFO "matroxfb: Unknown version (%u) of powerup infon", pins_version);
  871. return -1;
  872. }
  873. } else {
  874. pins_version = 1;
  875. }
  876. if (bd->pins_len != pinslen[pins_version - 1]) {
  877. printk(KERN_INFO "matroxfb: Invalid powerup infon");
  878. return -1;
  879. }
  880. switch (pins_version) {
  881. case 1:
  882. return parse_pins1(PMINFO bd);
  883. case 2:
  884. return parse_pins2(PMINFO bd);
  885. case 3:
  886. return parse_pins3(PMINFO bd);
  887. case 4:
  888. return parse_pins4(PMINFO bd);
  889. case 5:
  890. return parse_pins5(PMINFO bd);
  891. default:
  892. printk(KERN_DEBUG "matroxfb: Powerup info version %u is not yet supportedn", pins_version);
  893. return -1;
  894. }
  895. }
  896. void matroxfb_read_pins(WPMINFO2) {
  897. u32 opt;
  898. u32 biosbase;
  899. u32 fbbase;
  900. struct pci_dev* pdev = ACCESS_FBINFO(pcidev);
  901. memset(&ACCESS_FBINFO(bios), 0, sizeof(ACCESS_FBINFO(bios)));
  902. pci_read_config_dword(pdev, PCI_OPTION_REG, &opt);
  903. pci_write_config_dword(pdev, PCI_OPTION_REG, opt | PCI_OPTION_ENABLE_ROM);
  904. pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &biosbase);
  905. pci_read_config_dword(pdev, ACCESS_FBINFO(devflags.fbResource), &fbbase);
  906. pci_write_config_dword(pdev, PCI_ROM_ADDRESS, (fbbase & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
  907. parse_bios(vaddr_va(ACCESS_FBINFO(video).vbase), &ACCESS_FBINFO(bios));
  908. pci_write_config_dword(pdev, PCI_ROM_ADDRESS, biosbase);
  909. pci_write_config_dword(pdev, PCI_OPTION_REG, opt);
  910. matroxfb_set_limits(PMINFO &ACCESS_FBINFO(bios));
  911. }
  912. EXPORT_SYMBOL(matroxfb_DAC_in);
  913. EXPORT_SYMBOL(matroxfb_DAC_out);
  914. EXPORT_SYMBOL(matroxfb_var2my);
  915. EXPORT_SYMBOL(matroxfb_PLL_calcclock);
  916. #ifndef CONFIG_FB_MATROX_MULTIHEAD
  917. struct matrox_fb_info matroxfb_global_mxinfo;
  918. EXPORT_SYMBOL(matroxfb_global_mxinfo);
  919. #endif
  920. EXPORT_SYMBOL(matrox_text_loadfont); /* for matroxfb_accel */
  921. EXPORT_SYMBOL(matroxfb_createcursorshape); /* accel, DAC1064, Ti3026 */
  922. EXPORT_SYMBOL(matroxfb_fastfont_tryset); /* accel */
  923. EXPORT_SYMBOL(matroxfb_fastfont_init); /* DAC1064, Ti3026 */
  924. EXPORT_SYMBOL(matroxfb_vgaHWinit); /* DAC1064, Ti3026 */
  925. EXPORT_SYMBOL(matroxfb_vgaHWrestore); /* DAC1064, Ti3026 */
  926. EXPORT_SYMBOL(matroxfb_read_pins);
  927. MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec <vandrove@vc.cvut.cz>");
  928. MODULE_DESCRIPTION("Miscellaneous support for Matrox video cards");
  929. MODULE_LICENSE("GPL");