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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * SiS 300/630/730/540/315/550/650/740 frame buffer driver
  3.  * for Linux kernels 2.4.x and 2.5.x
  4.  *
  5.  * 2D acceleration part
  6.  *
  7.  * Based on the X driver's sis300_accel.c which is
  8.  *     Copyright Xavier Ducoin <x.ducoin@lectra.com>
  9.  *     Copyright 2002 by Thomas Winischhofer, Vienna, Austria
  10.  * and sis310_accel.c which is
  11.  *     Copyright 2002 by Thomas Winischhofer, Vienna, Austria
  12.  *
  13.  * Author: Thomas Winischhofer <thomas@winischhofer.net>
  14.  * (see http://www.winischhofer.net/
  15.  * for more information and updates)
  16.  */
  17. #include <linux/config.h>
  18. #include <linux/version.h>
  19. #include <linux/module.h>
  20. #include <linux/kernel.h>
  21. #include <linux/errno.h>
  22. #include <linux/string.h>
  23. #include <linux/mm.h>
  24. #include <linux/tty.h>
  25. #include <linux/slab.h>
  26. #include <linux/delay.h>
  27. #include <linux/fb.h>
  28. #include <linux/console.h>
  29. #include <linux/selection.h>
  30. #include <linux/ioport.h>
  31. #include <linux/init.h>
  32. #include <linux/pci.h>
  33. #include <linux/vt_kern.h>
  34. #include <linux/capability.h>
  35. #include <linux/fs.h>
  36. #include <linux/agp_backend.h>
  37. #include <linux/types.h>
  38. #include <linux/sisfb.h>
  39. #include <asm/io.h>
  40. #include <asm/mtrr.h>
  41. #include <video/fbcon.h>
  42. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
  43. #include <video/fbcon-cfb8.h>
  44. #include <video/fbcon-cfb16.h>
  45. #include <video/fbcon-cfb24.h>
  46. #include <video/fbcon-cfb32.h>
  47. #endif
  48. #include "osdef.h"
  49. #include "vgatypes.h"
  50. #include "vstruct.h"
  51. #include "sis_accel.h"
  52. #include "sis.h"
  53. extern struct     video_info ivideo;
  54. extern VGA_ENGINE sisvga_engine;
  55. static const int sisALUConv[] =
  56. {
  57.     0x00,       /* dest = 0;            0,      GXclear,        0 */
  58.     0x88,       /* dest &= src;         DSa,    GXand,          0x1 */
  59.     0x44,       /* dest = src & ~dest;  SDna,   GXandReverse,   0x2 */
  60.     0xCC,       /* dest = src;          S,      GXcopy,         0x3 */
  61.     0x22,       /* dest &= ~src;        DSna,   GXandInverted,  0x4 */
  62.     0xAA,       /* dest = dest;         D,      GXnoop,         0x5 */
  63.     0x66,       /* dest = ^src;         DSx,    GXxor,          0x6 */
  64.     0xEE,       /* dest |= src;         DSo,    GXor,           0x7 */
  65.     0x11,       /* dest = ~src & ~dest; DSon,   GXnor,          0x8 */
  66.     0x99,       /* dest ^= ~src ;       DSxn,   GXequiv,        0x9 */
  67.     0x55,       /* dest = ~dest;        Dn,     GXInvert,       0xA */
  68.     0xDD,       /* dest = src|~dest ;   SDno,   GXorReverse,    0xB */
  69.     0x33,       /* dest = ~src;         Sn,     GXcopyInverted, 0xC */
  70.     0xBB,       /* dest |= ~src;        DSno,   GXorInverted,   0xD */
  71.     0x77,       /* dest = ~src|~dest;   DSan,   GXnand,         0xE */
  72.     0xFF,       /* dest = 0xFF;         1,      GXset,          0xF */
  73. };
  74. /* same ROP but with Pattern as Source */
  75. static const int sisPatALUConv[] =
  76. {
  77.     0x00,       /* dest = 0;            0,      GXclear,        0 */
  78.     0xA0,       /* dest &= src;         DPa,    GXand,          0x1 */
  79.     0x50,       /* dest = src & ~dest;  PDna,   GXandReverse,   0x2 */
  80.     0xF0,       /* dest = src;          P,      GXcopy,         0x3 */
  81.     0x0A,       /* dest &= ~src;        DPna,   GXandInverted,  0x4 */
  82.     0xAA,       /* dest = dest;         D,      GXnoop,         0x5 */
  83.     0x5A,       /* dest = ^src;         DPx,    GXxor,          0x6 */
  84.     0xFA,       /* dest |= src;         DPo,    GXor,           0x7 */
  85.     0x05,       /* dest = ~src & ~dest; DPon,   GXnor,          0x8 */
  86.     0xA5,       /* dest ^= ~src ;       DPxn,   GXequiv,        0x9 */
  87.     0x55,       /* dest = ~dest;        Dn,     GXInvert,       0xA */
  88.     0xF5,       /* dest = src|~dest ;   PDno,   GXorReverse,    0xB */
  89.     0x0F,       /* dest = ~src;         Pn,     GXcopyInverted, 0xC */
  90.     0xAF,       /* dest |= ~src;        DPno,   GXorInverted,   0xD */
  91.     0x5F,       /* dest = ~src|~dest;   DPan,   GXnand,         0xE */
  92.     0xFF,       /* dest = 0xFF;         1,      GXset,          0xF */
  93. };
  94. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
  95. static const unsigned char myrops[] = {
  96.     3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  97.    };
  98. #endif
  99. /* 300 series */
  100. static void
  101. SiS300Sync(void)
  102. {
  103. SiS300Idle
  104. }
  105. static void
  106. SiS310Sync(void)
  107. {
  108. SiS310Idle
  109. }
  110. static void
  111. SiS300SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
  112.                                 unsigned int planemask, int trans_color)
  113. {
  114. SiS300SetupDSTColorDepth(ivideo.DstColor);
  115. SiS300SetupSRCPitch(ivideo.video_linelength)
  116. SiS300SetupDSTRect(ivideo.video_linelength, -1)
  117. if(trans_color != -1) {
  118. SiS300SetupROP(0x0A)
  119. SiS300SetupSRCTrans(trans_color)
  120. SiS300SetupCMDFlag(TRANSPARENT_BITBLT)
  121. } else {
  122.         SiS300SetupROP(sisALUConv[rop])
  123. }
  124. if(xdir > 0) {
  125. SiS300SetupCMDFlag(X_INC)
  126. }
  127. if(ydir > 0) {
  128. SiS300SetupCMDFlag(Y_INC)
  129. }
  130. }
  131. static void
  132. SiS300SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
  133.                                 int width, int height)
  134. {
  135. long srcbase, dstbase;
  136. srcbase = dstbase = 0;
  137. if (src_y >= 2048) {
  138. srcbase = ivideo.video_linelength * src_y;
  139. src_y = 0;
  140. }
  141. if (dst_y >= 2048) {
  142. dstbase = ivideo.video_linelength * dst_y;
  143. dst_y = 0;
  144. }
  145. SiS300SetupSRCBase(srcbase);
  146. SiS300SetupDSTBase(dstbase);
  147. if(!(ivideo.CommandReg & X_INC))  {
  148. src_x += width-1;
  149. dst_x += width-1;
  150. }
  151. if(!(ivideo.CommandReg & Y_INC))  {
  152. src_y += height-1;
  153. dst_y += height-1;
  154. }
  155. SiS300SetupRect(width, height)
  156. SiS300SetupSRCXY(src_x, src_y)
  157. SiS300SetupDSTXY(dst_x, dst_y)
  158. SiS300DoCMD
  159. }
  160. static void
  161. SiS300SetupForSolidFill(int color, int rop, unsigned int planemask)
  162. {
  163. SiS300SetupPATFG(color)
  164. SiS300SetupDSTRect(ivideo.video_linelength, -1)
  165. SiS300SetupDSTColorDepth(ivideo.DstColor);
  166. SiS300SetupROP(sisPatALUConv[rop])
  167. SiS300SetupCMDFlag(PATFG)
  168. }
  169. static void
  170. SiS300SubsequentSolidFillRect(int x, int y, int w, int h)
  171. {
  172. long dstbase;
  173. dstbase = 0;
  174. if(y >= 2048) {
  175. dstbase = ivideo.video_linelength * y;
  176. y = 0;
  177. }
  178. SiS300SetupDSTBase(dstbase)
  179. SiS300SetupDSTXY(x,y)
  180. SiS300SetupRect(w,h)
  181. SiS300SetupCMDFlag(X_INC | Y_INC | BITBLT)
  182. SiS300DoCMD
  183. }
  184. /* 310/325 series ------------------------------------------------ */
  185. static void
  186. SiS310SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
  187.                                 unsigned int planemask, int trans_color)
  188. {
  189. SiS310SetupDSTColorDepth(ivideo.DstColor);
  190. SiS310SetupSRCPitch(ivideo.video_linelength)
  191. SiS310SetupDSTRect(ivideo.video_linelength, -1)
  192. if (trans_color != -1) {
  193. SiS310SetupROP(0x0A)
  194. SiS310SetupSRCTrans(trans_color)
  195. SiS310SetupCMDFlag(TRANSPARENT_BITBLT)
  196. } else {
  197.         SiS310SetupROP(sisALUConv[rop])
  198. /* Set command - not needed, both 0 */
  199. /* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */
  200. }
  201. SiS310SetupCMDFlag(ivideo.SiS310_AccelDepth)
  202. /* TW: The 310/325 series is smart enough to know the direction */
  203. }
  204. static void
  205. SiS310SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
  206.                                 int width, int height)
  207. {
  208. long srcbase, dstbase;
  209. srcbase = dstbase = 0;
  210. if (src_y >= 2048) {
  211. srcbase = ivideo.video_linelength * src_y;
  212. src_y = 0;
  213. }
  214. if (dst_y >= 2048) {
  215. dstbase = ivideo.video_linelength * dst_y;
  216. dst_y = 0;
  217. }
  218. SiS310SetupSRCBase(srcbase);
  219. SiS310SetupDSTBase(dstbase);
  220. SiS310SetupRect(width, height)
  221. SiS310SetupSRCXY(src_x, src_y)
  222. SiS310SetupDSTXY(dst_x, dst_y)
  223. SiS310DoCMD
  224. }
  225. static void
  226. SiS310SetupForSolidFill(int color, int rop, unsigned int planemask)
  227. {
  228. SiS310SetupPATFG(color)
  229. SiS310SetupDSTRect(ivideo.video_linelength, -1)
  230. SiS310SetupDSTColorDepth(ivideo.DstColor);
  231. SiS310SetupROP(sisPatALUConv[rop])
  232. SiS310SetupCMDFlag(PATFG | ivideo.SiS310_AccelDepth)
  233. }
  234. static void
  235. SiS310SubsequentSolidFillRect(int x, int y, int w, int h)
  236. {
  237. long dstbase;
  238. dstbase = 0;
  239. if(y >= 2048) {
  240. dstbase = ivideo.video_linelength * y;
  241. y = 0;
  242. }
  243. SiS310SetupDSTBase(dstbase)
  244. SiS310SetupDSTXY(x,y)
  245. SiS310SetupRect(w,h)
  246. SiS310SetupCMDFlag(BITBLT)
  247. SiS310DoCMD
  248. }
  249. /* --------------------------------------------------------------------- */
  250. /* The exported routines */
  251. int sisfb_initaccel(void)
  252. {
  253. #ifdef SISFB_USE_SPINLOCKS
  254.     spin_lock_init(&ivideo.lockaccel);
  255. #endif
  256.     return(0);
  257. }
  258. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)  /* --- KERNEL 2.5.34 and later --- */
  259. void fbcon_sis_fillrect(struct fb_info *info, struct fb_fillrect *rect)
  260. {
  261.    CRITFLAGS
  262.    TWDEBUG("Inside sis_fillrect");
  263.    if(!rect->width || !rect->height)
  264.     return;
  265.    if(!sisfb_accel) {
  266.         cfb_fillrect(info, rect);
  267. return;
  268.    }
  269.    if(sisvga_engine == SIS_300_VGA) {
  270.    CRITBEGIN
  271.    SiS300SetupForSolidFill(rect->color, myrops[rect->rop], 0);
  272.    SiS300SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height);
  273.    CRITEND
  274.    SiS300Sync();
  275.    } else {
  276.    CRITBEGIN
  277.    SiS310SetupForSolidFill(rect->color, myrops[rect->rop], 0);
  278.    SiS310SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height);
  279.    CRITEND
  280.    SiS310Sync();
  281.    }
  282. }
  283. void fbcon_sis_copyarea(struct fb_info *info, struct fb_copyarea *area)
  284. {
  285.    int xdir, ydir;
  286.    CRITFLAGS
  287.    TWDEBUG("Inside sis_copyarea");
  288.    if(!sisfb_accel) {
  289.     cfb_copyarea(info, area);
  290. return;
  291.    }
  292.    if(!area->width || !area->height)
  293.     return;
  294.    if(area->sx < area->dx) xdir = 0;
  295.    else                    xdir = 1;
  296.    if(area->sy < area->dy) ydir = 0;
  297.    else                    ydir = 1;
  298.    if(sisvga_engine == SIS_300_VGA) {
  299.       CRITBEGIN
  300.       SiS300SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
  301.       SiS300SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height);
  302.       CRITEND
  303.       SiS300Sync();
  304.    } else {
  305.       CRITBEGIN
  306.       SiS310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
  307.       SiS310SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height);
  308.       CRITEND
  309.       SiS310Sync();
  310.    }
  311. }
  312. #endif
  313. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)  /* ------ KERNEL <2.5.34 ------ */
  314. void fbcon_sis_bmove(struct display *p, int srcy, int srcx,
  315.     int dsty, int dstx, int height, int width)
  316. {
  317.         int xdir, ydir;
  318. CRITFLAGS
  319. srcx *= fontwidth(p);
  320. srcy *= fontheight(p);
  321. dstx *= fontwidth(p);
  322. dsty *= fontheight(p);
  323. width *= fontwidth(p);
  324. height *= fontheight(p);
  325. if(srcx < dstx) xdir = 0;
  326. else            xdir = 1;
  327. if(srcy < dsty) ydir = 0;
  328. else            ydir = 1;
  329. if(sisvga_engine == SIS_300_VGA) {
  330.    CRITBEGIN
  331.    SiS300SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
  332.    SiS300SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height);
  333.    CRITEND
  334.    SiS300Sync();
  335. } else {
  336.    CRITBEGIN
  337.    SiS310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
  338.    SiS310SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height);
  339.    CRITEND
  340.    SiS310Sync();
  341. }
  342. }
  343. static void fbcon_sis_clear(struct vc_data *conp, struct display *p,
  344. int srcy, int srcx, int height, int width, int color)
  345. {
  346. CRITFLAGS
  347. srcx *= fontwidth(p);
  348. srcy *= fontheight(p);
  349. width *= fontwidth(p);
  350. height *= fontheight(p);
  351. if(sisvga_engine == SIS_300_VGA) {
  352.    CRITBEGIN
  353.    SiS300SetupForSolidFill(color, 3, 0);
  354.    SiS300SubsequentSolidFillRect(srcx, srcy, width, height);
  355.    CRITEND
  356.    SiS300Sync();
  357. } else {
  358.    CRITBEGIN
  359.    SiS310SetupForSolidFill(color, 3, 0);
  360.    SiS310SubsequentSolidFillRect(srcx, srcy, width, height);
  361.    CRITEND
  362.    SiS310Sync();
  363. }
  364. }
  365. void fbcon_sis_clear8(struct vc_data *conp, struct display *p,
  366. int srcy, int srcx, int height, int width)
  367. {
  368. u32 bgx;
  369. bgx = attr_bgcol_ec(p, conp);
  370. fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
  371. }
  372. void fbcon_sis_clear16(struct vc_data *conp, struct display *p,
  373. int srcy, int srcx, int height, int width)
  374. {
  375. u32 bgx;
  376. bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
  377. fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
  378. }
  379. void fbcon_sis_clear32(struct vc_data *conp, struct display *p,
  380. int srcy, int srcx, int height, int width)
  381. {
  382. u32 bgx;
  383. bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
  384. fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
  385. }
  386. void fbcon_sis_revc(struct display *p, int srcx, int srcy)
  387. {
  388. CRITFLAGS
  389. srcx *= fontwidth(p);
  390. srcy *= fontheight(p);
  391. if(sisvga_engine == SIS_300_VGA) {
  392.    CRITBEGIN
  393.    SiS300SetupForSolidFill(0, 0x0a, 0);
  394.    SiS300SubsequentSolidFillRect(srcx, srcy, fontwidth(p), fontheight(p));
  395.    CRITEND
  396.    SiS300Sync();
  397. } else {
  398.    CRITBEGIN
  399.    SiS310SetupForSolidFill(0, 0x0a, 0);
  400.    SiS310SubsequentSolidFillRect(srcx, srcy, fontwidth(p), fontheight(p));
  401.    CRITEND
  402.    SiS310Sync();
  403. }
  404. }
  405. #ifdef FBCON_HAS_CFB8
  406. struct display_switch fbcon_sis8 = {
  407. setup: fbcon_cfb8_setup,
  408. bmove: fbcon_sis_bmove,
  409. clear: fbcon_sis_clear8,
  410. putc: fbcon_cfb8_putc,
  411. putcs: fbcon_cfb8_putcs,
  412. revc: fbcon_cfb8_revc,
  413. clear_margins: fbcon_cfb8_clear_margins,
  414. fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
  415. };
  416. #endif
  417. #ifdef FBCON_HAS_CFB16
  418. struct display_switch fbcon_sis16 = {
  419. setup: fbcon_cfb16_setup,
  420. bmove: fbcon_sis_bmove,
  421. clear: fbcon_sis_clear16,
  422. putc: fbcon_cfb16_putc,
  423. putcs: fbcon_cfb16_putcs,
  424. revc: fbcon_sis_revc,
  425. clear_margins: fbcon_cfb16_clear_margins,
  426. fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
  427. };
  428. #endif
  429. #ifdef FBCON_HAS_CFB32
  430. struct display_switch fbcon_sis32 = {
  431. setup: fbcon_cfb32_setup,
  432. bmove: fbcon_sis_bmove,
  433. clear: fbcon_sis_clear32,
  434. putc: fbcon_cfb32_putc,
  435. putcs: fbcon_cfb32_putcs,
  436. revc: fbcon_sis_revc,
  437. clear_margins: fbcon_cfb32_clear_margins,
  438. fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
  439. };
  440. #endif
  441. #endif /* KERNEL VERSION */