matroxfb_misc.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:17k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *
  3.  * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
  4.  *
  5.  * (c) 1998,1999,2000 Petr Vandrovec <vandrove@vc.cvut.cz>
  6.  *
  7.  * Version: 1.54 2001/09/09
  8.  *
  9.  * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
  10.  *
  11.  * Contributors: "menion?" <menion@mindless.com>
  12.  *                     Betatesting, fixes, ideas
  13.  *
  14.  *               "Kurt Garloff" <garloff@suse.de>
  15.  *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
  16.  *
  17.  *               "Tom Rini" <trini@kernel.crashing.org>
  18.  *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
  19.  *
  20.  *               "Bibek Sahu" <scorpio@dodds.net>
  21.  *                     Access device through readb|w|l and write b|w|l
  22.  *                     Extensive debugging stuff
  23.  *
  24.  *               "Daniel Haun" <haund@usa.net>
  25.  *                     Testing, hardware cursor fixes
  26.  *
  27.  *               "Scott Wood" <sawst46+@pitt.edu>
  28.  *                     Fixes
  29.  *
  30.  *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
  31.  *                     Betatesting
  32.  *
  33.  *               "Kelly French" <targon@hazmat.com>
  34.  *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
  35.  *                     Betatesting, bug reporting
  36.  *
  37.  *               "Pablo Bianucci" <pbian@pccp.com.ar>
  38.  *                     Fixes, ideas, betatesting
  39.  *
  40.  *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
  41.  *                     Fixes, enhandcements, ideas, betatesting
  42.  *
  43.  *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
  44.  *                     PPC betatesting, PPC support, backward compatibility
  45.  *
  46.  *               "Paul Womar" <Paul@pwomar.demon.co.uk>
  47.  *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
  48.  *                     PPC betatesting
  49.  *
  50.  *               "Thomas Pornin" <pornin@bolet.ens.fr>
  51.  *                     Alpha betatesting
  52.  *
  53.  *               "Pieter van Leuven" <pvl@iae.nl>
  54.  *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
  55.  *                     G100 testing
  56.  *
  57.  *               "H. Peter Arvin" <hpa@transmeta.com>
  58.  *                     Ideas
  59.  *
  60.  *               "Cort Dougan" <cort@cs.nmt.edu>
  61.  *                     CHRP fixes and PReP cleanup
  62.  *
  63.  *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
  64.  *                     G400 support
  65.  *
  66.  *               "David C. Hansen" <haveblue@us.ibm.com>
  67.  *                     Fixes
  68.  *
  69.  * (following author is not in any relation with this code, but his code
  70.  *  is included in this driver)
  71.  *
  72.  * Based on framebuffer driver for VBE 2.0 compliant graphic boards
  73.  *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
  74.  *
  75.  * (following author is not in any relation with this code, but his ideas
  76.  *  were used when writting this driver)
  77.  *
  78.  *  FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
  79.  *
  80.  */
  81. /* make checkconfig does not check includes for this... */
  82. #include <linux/config.h>
  83. #include "matroxfb_misc.h"
  84. #include <linux/interrupt.h>
  85. #include <linux/matroxfb.h>
  86. void matroxfb_createcursorshape(WPMINFO struct display* p, int vmode) {
  87. unsigned int h;
  88. unsigned int cu, cd;
  89. h = fontheight(p);
  90. if (vmode & FB_VMODE_DOUBLE)
  91. h *= 2;
  92. cd = h;
  93. if (cd >= 10)
  94. cd--;
  95. switch (ACCESS_FBINFO(cursor.type) = (p->conp->vc_cursor_type & CUR_HWMASK)) {
  96. case CUR_NONE:
  97. cu = cd;
  98. break;
  99. case CUR_UNDERLINE:
  100. cu = cd - 2;
  101. break;
  102. case CUR_LOWER_THIRD:
  103. cu = (h * 2) / 3;
  104. break;
  105. case CUR_LOWER_HALF:
  106. cu = h / 2;
  107. break;
  108. case CUR_TWO_THIRDS:
  109. cu = h / 3;
  110. break;
  111. case CUR_BLOCK:
  112. default:
  113. cu = 0;
  114. cd = h;
  115. break;
  116. }
  117. ACCESS_FBINFO(cursor.w) = fontwidth(p);
  118. ACCESS_FBINFO(cursor.u) = cu;
  119. ACCESS_FBINFO(cursor.d) = cd;
  120. }
  121. void matroxfb_DAC_out(CPMINFO int reg, int val) {
  122. DBG_REG("outDAC");
  123. mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
  124. mga_outb(M_RAMDAC_BASE+M_X_DATAREG, val);
  125. }
  126. int matroxfb_DAC_in(CPMINFO int reg) {
  127. DBG_REG("inDAC");
  128. mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
  129. return mga_inb(M_RAMDAC_BASE+M_X_DATAREG);
  130. }
  131. void matroxfb_var2my(struct fb_var_screeninfo* var, struct my_timming* mt) {
  132. unsigned int pixclock = var->pixclock;
  133. DBG("var2my")
  134. if (!pixclock) pixclock = 10000; /* 10ns = 100MHz */
  135. mt->pixclock = 1000000000 / pixclock;
  136. if (mt->pixclock < 1) mt->pixclock = 1;
  137. mt->dblscan = var->vmode & FB_VMODE_DOUBLE;
  138. mt->interlaced = var->vmode & FB_VMODE_INTERLACED;
  139. mt->HDisplay = var->xres;
  140. mt->HSyncStart = mt->HDisplay + var->right_margin;
  141. mt->HSyncEnd = mt->HSyncStart + var->hsync_len;
  142. mt->HTotal = mt->HSyncEnd + var->left_margin;
  143. mt->VDisplay = var->yres;
  144. mt->VSyncStart = mt->VDisplay + var->lower_margin;
  145. mt->VSyncEnd = mt->VSyncStart + var->vsync_len;
  146. mt->VTotal = mt->VSyncEnd + var->upper_margin;
  147. mt->sync = var->sync;
  148. }
  149. int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int freq, unsigned int fmax,
  150. unsigned int* in, unsigned int* feed, unsigned int* post) {
  151. unsigned int bestdiff = ~0;
  152. unsigned int bestvco = 0;
  153. unsigned int fxtal = pll->ref_freq;
  154. unsigned int fwant;
  155. unsigned int p;
  156. DBG("PLL_calcclock")
  157. fwant = freq;
  158. #ifdef DEBUG
  159. printk(KERN_ERR "post_shift_max: %dn", pll->post_shift_max);
  160. printk(KERN_ERR "ref_freq: %dn", pll->ref_freq);
  161. printk(KERN_ERR "freq: %dn", freq);
  162. printk(KERN_ERR "vco_freq_min: %dn", pll->vco_freq_min);
  163. printk(KERN_ERR "in_div_min: %dn", pll->in_div_min);
  164. printk(KERN_ERR "in_div_max: %dn", pll->in_div_max);
  165. printk(KERN_ERR "feed_div_min: %dn", pll->feed_div_min);
  166. printk(KERN_ERR "feed_div_max: %dn", pll->feed_div_max);
  167. printk(KERN_ERR "fmax: %dn", fmax);
  168. #endif
  169. for (p = 1; p <= pll->post_shift_max; p++) {
  170. if (fwant * 2 > fmax)
  171. break;
  172. fwant *= 2;
  173. }
  174. if (fwant < pll->vco_freq_min) fwant = pll->vco_freq_min;
  175. if (fwant > fmax) fwant = fmax;
  176. for (; p-- > 0; fwant >>= 1, bestdiff >>= 1) {
  177. unsigned int m;
  178. if (fwant < pll->vco_freq_min) break;
  179. for (m = pll->in_div_min; m <= pll->in_div_max; m++) {
  180. unsigned int diff, fvco;
  181. unsigned int n;
  182. n = (fwant * (m + 1) + (fxtal >> 1)) / fxtal - 1;
  183. if (n > pll->feed_div_max)
  184. break;
  185. if (n < pll->feed_div_min)
  186. n = pll->feed_div_min;
  187. fvco = (fxtal * (n + 1)) / (m + 1);
  188. if (fvco < fwant)
  189. diff = fwant - fvco;
  190. else
  191. diff = fvco - fwant;
  192. if (diff < bestdiff) {
  193. bestdiff = diff;
  194. *post = p;
  195. *in = m;
  196. *feed = n;
  197. bestvco = fvco;
  198. }
  199. }
  200. }
  201. dprintk(KERN_ERR "clk: %02X %02X %02X %d %d %dn", *in, *feed, *post, fxtal, bestvco, fwant);
  202. return bestvco;
  203. }
  204. int matroxfb_vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
  205. unsigned int hd, hs, he, hbe, ht;
  206. unsigned int vd, vs, ve, vt;
  207. unsigned int wd;
  208. unsigned int divider;
  209. int i;
  210. int text = p->type == FB_TYPE_TEXT;
  211. int fwidth;
  212. if (text) {
  213. fwidth = fontwidth(p);
  214. if (!fwidth) fwidth = 8;
  215. } else
  216. fwidth = 8;
  217. DBG("vgaHWinit")
  218. hw->SEQ[0] = 0x00;
  219. if (fwidth == 9)
  220. hw->SEQ[1] = 0x00;
  221. else
  222. hw->SEQ[1] = 0x01; /* or 0x09 */
  223. hw->SEQ[2] = 0x0F; /* bitplanes */
  224. hw->SEQ[3] = 0x00;
  225. if (text)
  226. hw->SEQ[4] = 0x02;
  227. else
  228. hw->SEQ[4] = 0x0E;
  229. /* CRTC 0..7, 9, 16..19, 21, 22 are reprogrammed by Matrox Millennium code... Hope that by MGA1064 too */
  230. if (m->dblscan) {
  231. m->VTotal <<= 1;
  232. m->VDisplay <<= 1;
  233. m->VSyncStart <<= 1;
  234. m->VSyncEnd <<= 1;
  235. }
  236. if (m->interlaced) {
  237. m->VTotal >>= 1;
  238. m->VDisplay >>= 1;
  239. m->VSyncStart >>= 1;
  240. m->VSyncEnd >>= 1;
  241. }
  242. /* GCTL is ignored when not using 0xA0000 aperture */
  243. hw->GCTL[0] = 0x00;
  244. hw->GCTL[1] = 0x00;
  245. hw->GCTL[2] = 0x00;
  246. hw->GCTL[3] = 0x00;
  247. hw->GCTL[4] = 0x00;
  248. if (text) {
  249. hw->GCTL[5] = 0x10;
  250. hw->GCTL[6] = 0x02;
  251. } else {
  252. hw->GCTL[5] = 0x40;
  253. hw->GCTL[6] = 0x05;
  254. }
  255. hw->GCTL[7] = 0x0F;
  256. hw->GCTL[8] = 0xFF;
  257. /* Whole ATTR is ignored in PowerGraphics mode */
  258. for (i = 0; i < 16; i++)
  259. hw->ATTR[i] = i;
  260. if (text) {
  261. hw->ATTR[16] = 0x04;
  262. } else {
  263. hw->ATTR[16] = 0x41;
  264. }
  265. hw->ATTR[17] = 0xFF;
  266. hw->ATTR[18] = 0x0F;
  267. if (fwidth == 9)
  268. hw->ATTR[19] = 0x08;
  269. else
  270. hw->ATTR[19] = 0x00;
  271. hw->ATTR[20] = 0x00;
  272. if (text) {
  273. hd = m->HDisplay / fwidth;
  274. hs = m->HSyncStart / fwidth;
  275. he = m->HSyncEnd / fwidth;
  276. ht = m->HTotal / fwidth;
  277. divider = 8;
  278. } else {
  279. hd = m->HDisplay >> 3;
  280. hs = m->HSyncStart >> 3;
  281. he = m->HSyncEnd >> 3;
  282. ht = m->HTotal >> 3;
  283. /* standard timmings are in 8pixels, but for interleaved we cannot */
  284. /* do it for 4bpp (because of (4bpp >> 1(interleaved))/4 == 0) */
  285. /* using 16 or more pixels per unit can save us */
  286. divider = ACCESS_FBINFO(curr.final_bppShift);
  287. }
  288. while (divider & 3) {
  289. hd >>= 1;
  290. hs >>= 1;
  291. he >>= 1;
  292. ht >>= 1;
  293. divider <<= 1;
  294. }
  295. divider = divider / 4;
  296. /* divider can be from 1 to 8 */
  297. while (divider > 8) {
  298. hd <<= 1;
  299. hs <<= 1;
  300. he <<= 1;
  301. ht <<= 1;
  302. divider >>= 1;
  303. }
  304. hd = hd - 1;
  305. hs = hs - 1;
  306. he = he - 1;
  307. ht = ht - 1;
  308. vd = m->VDisplay - 1;
  309. vs = m->VSyncStart - 1;
  310. ve = m->VSyncEnd - 1;
  311. vt = m->VTotal - 2;
  312. /* G200 cannot work with (ht & 7) == 6 */
  313. if (((ht & 0x07) == 0x06) || ((ht & 0x0F) == 0x04))
  314. ht++;
  315. if (text) {
  316. hbe = ht - 1;
  317. wd = p->var.xres_virtual / (fwidth * 2);
  318. } else {
  319. hbe = ht;
  320. wd = p->var.xres_virtual * ACCESS_FBINFO(curr.final_bppShift) / 64;
  321. }
  322. hw->CRTCEXT[0] = 0;
  323. hw->CRTCEXT[5] = 0;
  324. if (m->interlaced) {
  325. hw->CRTCEXT[0] = 0x80;
  326. hw->CRTCEXT[5] = (hs + he - ht) >> 1;
  327. if (!m->dblscan)
  328. wd <<= 1;
  329. vt &= ~1;
  330. }
  331. hw->CRTCEXT[0] |=  (wd & 0x300) >> 4;
  332. hw->CRTCEXT[1] = (((ht - 4) & 0x100) >> 8) |
  333.   ((hd      & 0x100) >> 7) | /* blanking */
  334.   ((hs      & 0x100) >> 6) | /* sync start */
  335.    (hbe     & 0x040);  /* end hor. blanking */
  336. if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY)
  337. hw->CRTCEXT[1] |= 0x88; /* enable horizontal and vertical vidrst */
  338. hw->CRTCEXT[2] =  ((vt & 0xC00) >> 10) |
  339.   ((vd & 0x400) >>  8) | /* disp end */
  340.   ((vd & 0xC00) >>  7) | /* vblanking start */
  341.   ((vs & 0xC00) >>  5);
  342. if (text)
  343. hw->CRTCEXT[3] = 0x00;
  344. else
  345. hw->CRTCEXT[3] = (divider - 1) | 0x80;
  346. hw->CRTCEXT[4] = 0;
  347. hw->CRTC[0] = ht-4;
  348. hw->CRTC[1] = hd;
  349. hw->CRTC[2] = hd;
  350. hw->CRTC[3] = (hbe & 0x1F) | 0x80;
  351. hw->CRTC[4] = hs;
  352. hw->CRTC[5] = ((hbe & 0x20) << 2) | (he & 0x1F);
  353. if (text)
  354. hw->CRTC[5] |= 0x60; /* delay sync for 3 clocks (to same picture position on MGA and VGA) */
  355. hw->CRTC[6] = vt & 0xFF;
  356. hw->CRTC[7] = ((vt & 0x100) >> 8) |
  357.       ((vd & 0x100) >> 7) |
  358.       ((vs & 0x100) >> 6) |
  359.       ((vd & 0x100) >> 5) |
  360.       0x10                |
  361.       ((vt & 0x200) >> 4) |
  362.       ((vd & 0x200) >> 3) |
  363.       ((vs & 0x200) >> 2);
  364. hw->CRTC[8] = 0x00;
  365. hw->CRTC[9] = ((vd & 0x200) >> 4) | 0x40;
  366. if (text)
  367. hw->CRTC[9] |= fontheight(p) - 1;
  368. if (m->dblscan && !m->interlaced)
  369. hw->CRTC[9] |= 0x80;
  370. for (i = 10; i < 16; i++)
  371. hw->CRTC[i] = 0x00;
  372. hw->CRTC[16] = vs /* & 0xFF */;
  373. hw->CRTC[17] = (ve & 0x0F) | 0x20;
  374. hw->CRTC[18] = vd /* & 0xFF */;
  375. hw->CRTC[19] = wd /* & 0xFF */;
  376. hw->CRTC[20] = 0x00;
  377. hw->CRTC[21] = vd /* & 0xFF */;
  378. hw->CRTC[22] = (vt + 1) /* & 0xFF */;
  379. if (text) {
  380. if (ACCESS_FBINFO(devflags.textmode) == 1)
  381. hw->CRTC[23] = 0xC3;
  382. else
  383. hw->CRTC[23] = 0xA3;
  384. if (ACCESS_FBINFO(devflags.textmode) == 4)
  385. hw->CRTC[20] = 0x5F;
  386. else
  387. hw->CRTC[20] = 0x1F;
  388. } else
  389. hw->CRTC[23] = 0xC3;
  390. hw->CRTC[24] = 0xFF;
  391. return 0;
  392. };
  393. void matroxfb_vgaHWrestore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw) {
  394. int i;
  395. CRITFLAGS
  396. DBG("vgaHWrestore")
  397. dprintk(KERN_INFO "MiscOutReg: %02Xn", hw->MiscOutReg);
  398. dprintk(KERN_INFO "SEQ regs:   ");
  399. for (i = 0; i < 5; i++)
  400. dprintk("%02X:", hw->SEQ[i]);
  401. dprintk("n");
  402. dprintk(KERN_INFO "GDC regs:   ");
  403. for (i = 0; i < 9; i++)
  404. dprintk("%02X:", hw->GCTL[i]);
  405. dprintk("n");
  406. dprintk(KERN_INFO "CRTC regs: ");
  407. for (i = 0; i < 25; i++)
  408. dprintk("%02X:", hw->CRTC[i]);
  409. dprintk("n");
  410. dprintk(KERN_INFO "ATTR regs: ");
  411. for (i = 0; i < 21; i++)
  412. dprintk("%02X:", hw->ATTR[i]);
  413. dprintk("n");
  414. CRITBEGIN
  415. mga_inb(M_ATTR_RESET);
  416. mga_outb(M_ATTR_INDEX, 0);
  417. mga_outb(M_MISC_REG, hw->MiscOutReg);
  418. for (i = 1; i < 5; i++)
  419. mga_setr(M_SEQ_INDEX, i, hw->SEQ[i]);
  420. mga_setr(M_CRTC_INDEX, 17, hw->CRTC[17] & 0x7F);
  421. for (i = 0; i < 25; i++)
  422. mga_setr(M_CRTC_INDEX, i, hw->CRTC[i]);
  423. for (i = 0; i < 9; i++)
  424. mga_setr(M_GRAPHICS_INDEX, i, hw->GCTL[i]);
  425. for (i = 0; i < 21; i++) {
  426. mga_inb(M_ATTR_RESET);
  427. mga_outb(M_ATTR_INDEX, i);
  428. mga_outb(M_ATTR_INDEX, hw->ATTR[i]);
  429. }
  430. mga_outb(M_PALETTE_MASK, 0xFF);
  431. mga_outb(M_DAC_REG, 0x00);
  432. for (i = 0; i < 768; i++)
  433. mga_outb(M_DAC_VAL, hw->DACpal[i]);
  434. mga_inb(M_ATTR_RESET);
  435. mga_outb(M_ATTR_INDEX, 0x20);
  436. CRITEND
  437. }
  438. void matroxfb_fastfont_init(struct matrox_fb_info* minfo){
  439. unsigned int size;
  440. size = ACCESS_FBINFO(fastfont.size);
  441. ACCESS_FBINFO(fastfont.size) = 0;
  442. if (size) {
  443. unsigned int end = ACCESS_FBINFO(video.len_usable);
  444. if (size < end) {
  445. unsigned int start;
  446. start = (end - size) & PAGE_MASK;
  447. if (start >= 0x00100000) {
  448. ACCESS_FBINFO(video.len_usable) = start;
  449. ACCESS_FBINFO(fastfont.mgabase) = start * 8;
  450. ACCESS_FBINFO(fastfont.vbase) = ACCESS_FBINFO(video.vbase);
  451. vaddr_add(&ACCESS_FBINFO(fastfont.vbase), start);
  452. ACCESS_FBINFO(fastfont.size) = end - start;
  453. }
  454. }
  455. }
  456. }
  457. #ifndef FNTCHARCNT
  458. #define FNTCHARCNT(fd) (((int *)(fd))[-3])
  459. #endif
  460. int matrox_text_loadfont(WPMINFO struct display* p) {
  461. unsigned int fsize;
  462. unsigned int width;
  463. vaddr_t dst;
  464. unsigned int i;
  465. u_int8_t* font;
  466. CRITFLAGS
  467. if (!p || !p->fontdata)
  468. return 0;
  469. width = fontwidth(p);
  470. fsize = p->userfont?FNTCHARCNT(p->fontdata):256;
  471. dst = ACCESS_FBINFO(video.vbase);
  472. i = 2;
  473. font = (u_int8_t*)p->fontdata;
  474. CRITBEGIN
  475. mga_setr(M_SEQ_INDEX, 0x02, 0x04);
  476. while (fsize--) {
  477. int l;
  478. for (l = 0; l < fontheight(p); l++) {
  479. mga_writeb(dst, i, *font++);
  480. if (fontwidth(p) > 8) font++;
  481. i += ACCESS_FBINFO(devflags.vgastep);
  482. }
  483. i += (32 - fontheight(p)) * ACCESS_FBINFO(devflags.vgastep);
  484. }
  485. mga_setr(M_SEQ_INDEX, 0x02, 0x03);
  486. CRITEND
  487. return 1;
  488. }
  489. int matroxfb_fastfont_tryset(WPMINFO struct display* p) {
  490. unsigned int fsize;
  491. unsigned int width;
  492. CRITFLAGS
  493. if (!p || !p->fontdata)
  494. return 0;
  495. width = fontwidth(p);
  496. if (width > 32)
  497. return 0;
  498. fsize = (p->userfont?FNTCHARCNT(p->fontdata):256) * fontheight(p);
  499. if (((fsize * width + 31) / 32) * 4 > ACCESS_FBINFO(fastfont.size))
  500. return 0;
  501. CRITBEGIN
  502. mga_outl(M_OPMODE, M_OPMODE_8BPP);
  503. if (width <= 8) {
  504. if (width == 8)
  505. mga_memcpy_toio(ACCESS_FBINFO(fastfont.vbase), 0, p->fontdata, fsize);
  506. else {
  507. vaddr_t dst;
  508. unsigned int i;
  509. u_int8_t* font;
  510. u_int32_t mask, valid, reg;
  511. dst = ACCESS_FBINFO(fastfont.vbase);
  512. font = (u_int8_t*)p->fontdata;
  513. mask = ~0 << (8 - width);
  514. valid = 0;
  515. reg = 0;
  516. i = 0;
  517. while (fsize--) {
  518. reg |= (*font++ & mask) << (8 - valid);
  519. valid += width;
  520. if (valid >= 8) {
  521. mga_writeb(dst, i++, reg >> 8);
  522. reg = reg << 8;
  523. valid -= 8;
  524. }
  525. }
  526. if (valid)
  527. mga_writeb(dst, i, reg >> 8);
  528. }
  529. } else if (width <= 16) {
  530. if (width == 16)
  531. mga_memcpy_toio(ACCESS_FBINFO(fastfont.vbase), 0, p->fontdata, fsize*2);
  532. else {
  533. vaddr_t dst;
  534. u_int16_t* font;
  535. u_int32_t mask, valid, reg;
  536. unsigned int i;
  537. dst = ACCESS_FBINFO(fastfont.vbase);
  538. font = (u_int16_t*)p->fontdata;
  539. mask = ~0 << (16 - width);
  540. valid = 0;
  541. reg = 0;
  542. i = 0;
  543. while (fsize--) {
  544. reg |= (ntohs(*font++) & mask) << (16 - valid);
  545. valid += width;
  546. if (valid >= 16) {
  547. mga_writew(dst, i, htons(reg >> 16));
  548. i += 2;
  549. reg = reg << 16;
  550. valid -= 16;
  551. }
  552. }
  553. if (valid)
  554. mga_writew(dst, i, htons(reg >> 16));
  555. }
  556. } else {
  557. if (width == 32)
  558. mga_memcpy_toio(ACCESS_FBINFO(fastfont.vbase), 0, p->fontdata, fsize*4);
  559. else {
  560. vaddr_t dst;
  561. u_int32_t* font;
  562. u_int32_t mask, valid, reg;
  563. unsigned int i;
  564. dst = ACCESS_FBINFO(fastfont.vbase);
  565. font = (u_int32_t*)p->fontdata;
  566. mask = ~0 << (32 - width);
  567. valid = 0;
  568. reg = 0;
  569. i = 0;
  570. while (fsize--) {
  571. reg |= (ntohl(*font) & mask) >> valid;
  572. valid += width;
  573. if (valid >= 32) {
  574. mga_writel(dst, i, htonl(reg));
  575. i += 4;
  576. valid -= 32;
  577. if (valid)
  578. reg = (ntohl(*font) & mask) << (width - valid);
  579. else
  580. reg = 0;
  581. }
  582. font++;
  583. }
  584. if (valid)
  585. mga_writel(dst, i, htonl(reg));
  586. }
  587. }
  588. mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
  589. CRITEND
  590. return 1;
  591. }
  592. EXPORT_SYMBOL(matroxfb_DAC_in);
  593. EXPORT_SYMBOL(matroxfb_DAC_out);
  594. EXPORT_SYMBOL(matroxfb_var2my);
  595. EXPORT_SYMBOL(matroxfb_PLL_calcclock);
  596. #ifndef CONFIG_FB_MATROX_MULTIHEAD
  597. struct matrox_fb_info matroxfb_global_mxinfo;
  598. EXPORT_SYMBOL(matroxfb_global_mxinfo);
  599. #endif
  600. EXPORT_SYMBOL(matrox_text_loadfont); /* for matroxfb_accel */
  601. EXPORT_SYMBOL(matroxfb_createcursorshape); /* accel, DAC1064, Ti3026 */
  602. EXPORT_SYMBOL(matroxfb_fastfont_tryset); /* accel */
  603. EXPORT_SYMBOL(matroxfb_fastfont_init); /* DAC1064, Ti3026 */
  604. EXPORT_SYMBOL(matroxfb_vgaHWinit); /* DAC1064, Ti3026 */
  605. EXPORT_SYMBOL(matroxfb_vgaHWrestore); /* DAC1064, Ti3026 */
  606. MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec <vandrove@vc.cvut.cz>");
  607. MODULE_DESCRIPTION("Miscellaneous support for Matrox video cards");
  608. MODULE_LICENSE("GPL");