mga_vid.c
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:18k
源码类别:

DVD

开发平台:

Unix_Linux

  1. /*
  2.  *
  3.  * mga_vid.c
  4.  *
  5.  * Copyright (C) 1999 Aaron Holtzman
  6.  * 
  7.  * Module skeleton based on gutted agpgart module by Jeff Hartmann 
  8.  * <slicer@ionet.net>
  9.  *
  10.  * Matrox MGA G200/G400 YUV Video Interface module Version 0.1.0
  11.  * 
  12.  * BES == Back End Scaler
  13.  * 
  14.  * This software has been released under the terms of the GNU Public
  15.  * license. See http://www.gnu.org/copyleft/gpl.html for details.
  16.  */
  17. //It's entirely possible this major conflicts with something else
  18. /* mknod /dev/mga_vid c 178 0 */
  19. #include <linux/config.h>
  20. #include <linux/version.h>
  21. #include <linux/module.h>
  22. #include <linux/types.h>
  23. #include <linux/kernel.h>
  24. #include <linux/sched.h>
  25. #include <linux/mm.h>
  26. #include <linux/string.h>
  27. #include <linux/errno.h>
  28. #include <linux/malloc.h>
  29. #include <linux/pci.h>
  30. #include <linux/init.h>
  31. #include <linux/videodev.h>
  32. #include "mga_vid.h"
  33. #ifdef CONFIG_MTRR 
  34. #include <asm/mtrr.h>
  35. #endif
  36. #include <asm/uaccess.h>
  37. #include <asm/system.h>
  38. #include <asm/io.h>
  39. #define TRUE 1
  40. #define FALSE 0
  41. #define MGA_VID_MAJOR 178
  42. #define MGA_VIDMEM_SIZE 16
  43. #ifndef PCI_DEVICE_ID_MATROX_G200_PCI 
  44. #define PCI_DEVICE_ID_MATROX_G200_PCI 0x0520
  45. #endif
  46. #ifndef PCI_DEVICE_ID_MATROX_G200_AGP 
  47. #define PCI_DEVICE_ID_MATROX_G200_AGP 0x0521
  48. #endif
  49. #ifndef PCI_DEVICE_ID_MATROX_G400 
  50. #define PCI_DEVICE_ID_MATROX_G400 0x0525
  51. #endif
  52. MODULE_AUTHOR("Aaron Holtzman <aholtzma@engr.uvic.ca>");
  53. typedef struct bes_registers_s
  54. {
  55. //BES Control
  56. uint_32 besctl;
  57. //BES Global control
  58. uint_32 besglobctl;
  59. //Luma control (brightness and contrast)
  60. uint_32 beslumactl;
  61. //Line pitch
  62. uint_32 bespitch;
  63. //Buffer A-1 Chroma 3 plane org
  64. uint_32 besa1c3org;
  65. //Buffer A-1 Chroma org
  66. uint_32 besa1corg;
  67. //Buffer A-1 Luma org
  68. uint_32 besa1org;
  69. //Buffer A-2 Chroma 3 plane org
  70. uint_32 besa2c3org;
  71. //Buffer A-2 Chroma org
  72. uint_32 besa2corg;
  73. //Buffer A-2 Luma org
  74. uint_32 besa2org;
  75. //Buffer B-1 Chroma 3 plane org
  76. uint_32 besb1c3org;
  77. //Buffer B-1 Chroma org
  78. uint_32 besb1corg;
  79. //Buffer B-1 Luma org
  80. uint_32 besb1org;
  81. //Buffer B-2 Chroma 3 plane org
  82. uint_32 besb2c3org;
  83. //Buffer B-2 Chroma org
  84. uint_32 besb2corg;
  85. //Buffer B-2 Luma org
  86. uint_32 besb2org;
  87. //BES Horizontal coord
  88. uint_32 beshcoord;
  89. //BES Horizontal inverse scaling [5.14]
  90. uint_32 beshiscal;
  91. //BES Horizontal source start [10.14] (for scaling)
  92. uint_32 beshsrcst;
  93. //BES Horizontal source ending [10.14] (for scaling) 
  94. uint_32 beshsrcend;
  95. //BES Horizontal source last 
  96. uint_32 beshsrclst;
  97. //BES Vertical coord
  98. uint_32 besvcoord;
  99. //BES Vertical inverse scaling [5.14]
  100. uint_32 besviscal;
  101. //BES Field 1 vertical source last position
  102. uint_32 besv1srclst;
  103. //BES Field 1 weight start
  104. uint_32 besv1wght;
  105. //BES Field 2 vertical source last position
  106. uint_32 besv2srclst;
  107. //BES Field 2 weight start
  108. uint_32 besv2wght;
  109. } bes_registers_t;
  110. static bes_registers_t regs;
  111. static uint_32 mga_vid_in_use = 0;
  112. static uint_32 is_g400 = 0;
  113. static uint_32 vid_src_ready = 0;
  114. static uint_32 vid_overlay_on = 0;
  115. static uint_8 *mga_mmio_base = 0;
  116. static uint_32 mga_mem_base = 0; 
  117. static uint_32 mga_src_base = 0;
  118. static struct pci_dev *pci_dev;
  119. static struct video_window mga_win;
  120. static mga_vid_config_t mga_config; 
  121. //All register offsets are converted to word aligned offsets (32 bit)
  122. //because we want all our register accesses to be 32 bits
  123. #define VCOUNT      0x1e20
  124. #define PALWTADD      0x3c00 // Index register for X_DATAREG port
  125. #define X_DATAREG     0x3c0a
  126. #define XMULCTRL      0x19
  127. #define BPP_8         0x00
  128. #define BPP_15        0x01
  129. #define BPP_16        0x02
  130. #define BPP_24        0x03
  131. #define BPP_32_DIR    0x04
  132. #define BPP_32_PAL    0x07
  133. #define XCOLMSK       0x40
  134. #define X_COLKEY      0x42
  135. #define XKEYOPMODE    0x51
  136. #define XCOLMSK0RED   0x52
  137. #define XCOLMSK0GREEN 0x53
  138. #define XCOLMSK0BLUE  0x54
  139. #define XCOLKEY0RED   0x55
  140. #define XCOLKEY0GREEN 0x56
  141. #define XCOLKEY0BLUE  0x57
  142. // Backend Scaler registers
  143. #define BESCTL      0x3d20
  144. #define BESGLOBCTL  0x3dc0
  145. #define BESLUMACTL  0x3d40
  146. #define BESPITCH    0x3d24
  147. #define BESA1C3ORG  0x3d60
  148. #define BESA1CORG   0x3d10
  149. #define BESA1ORG    0x3d00
  150. #define BESHCOORD   0x3d28
  151. #define BESHISCAL   0x3d30
  152. #define BESHSRCEND  0x3d3C
  153. #define BESHSRCLST  0x3d50
  154. #define BESHSRCST   0x3d38
  155. #define BESV1WGHT   0x3d48
  156. #define BESV2WGHT   0x3d4c
  157. #define BESV1SRCLST 0x3d54
  158. #define BESV2SRCLST 0x3d58
  159. #define BESVISCAL   0x3d34
  160. #define BESVCOORD   0x3d2c
  161. #define BESSTATUS   0x3dc4
  162. static void mga_vid_write_regs(void)
  163. {
  164. //Make sure internal registers don't get updated until we're done
  165. writel( (readl(mga_mmio_base + VCOUNT)-1)<<16,
  166. mga_mmio_base + BESGLOBCTL);
  167. // color or coordinate keying
  168. writeb( XKEYOPMODE, mga_mmio_base + PALWTADD);
  169. writeb( mga_config.colkey_on, mga_mmio_base + X_DATAREG);
  170. if ( mga_config.colkey_on ) 
  171. {
  172. uint_32 r=0, g=0, b=0;
  173. writeb( XMULCTRL, mga_mmio_base + PALWTADD);
  174. switch (readb (mga_mmio_base + X_DATAREG)) 
  175. {
  176. case BPP_8:
  177. /* Need to look up the color index, just using
  178.  color 0 for now. */
  179. break;
  180. case BPP_15:
  181. r = mga_config.colkey_red   >> 3;
  182. g = mga_config.colkey_green >> 3;
  183. b = mga_config.colkey_blue  >> 3;
  184. break;
  185. case BPP_16:
  186. r = mga_config.colkey_red   >> 3;
  187. g = mga_config.colkey_green >> 2;
  188. b = mga_config.colkey_blue  >> 3;
  189. break;
  190. case BPP_24:
  191. case BPP_32_DIR:
  192. case BPP_32_PAL:
  193. r = mga_config.colkey_red;
  194. g = mga_config.colkey_green;
  195. b = mga_config.colkey_blue;
  196. break;
  197. }
  198. // Disable color keying on alpha channel 
  199. writeb( XCOLMSK, mga_mmio_base + PALWTADD);
  200. writeb( 0x00, mga_mmio_base + X_DATAREG);
  201. writeb( X_COLKEY, mga_mmio_base + PALWTADD);
  202. writeb( 0x00, mga_mmio_base + X_DATAREG);
  203. // Set up color key registers
  204. writeb( XCOLKEY0RED, mga_mmio_base + PALWTADD);
  205. writeb( r, mga_mmio_base + X_DATAREG);
  206. writeb( XCOLKEY0GREEN, mga_mmio_base + PALWTADD);
  207. writeb( g, mga_mmio_base + X_DATAREG);
  208. writeb( XCOLKEY0BLUE, mga_mmio_base + PALWTADD);
  209. writeb( b, mga_mmio_base + X_DATAREG);
  210. // Set up color key mask registers
  211. writeb( XCOLMSK0RED, mga_mmio_base + PALWTADD);
  212. writeb( 0xff, mga_mmio_base + X_DATAREG);
  213. writeb( XCOLMSK0GREEN, mga_mmio_base + PALWTADD);
  214. writeb( 0xff, mga_mmio_base + X_DATAREG);
  215. writeb( XCOLMSK0BLUE, mga_mmio_base + PALWTADD);
  216. writeb( 0xff, mga_mmio_base + X_DATAREG);
  217. }
  218. // Backend Scaler
  219. writel( regs.besctl,      mga_mmio_base + BESCTL); 
  220. if(is_g400)
  221. writel( regs.beslumactl,  mga_mmio_base + BESLUMACTL); 
  222. writel( regs.bespitch,    mga_mmio_base + BESPITCH); 
  223. writel( regs.besa1org,    mga_mmio_base + BESA1ORG);
  224. writel( regs.besa1corg,   mga_mmio_base + BESA1CORG);
  225. if(is_g400)
  226. writel( regs.besa1c3org,  mga_mmio_base + BESA1C3ORG);
  227. writel( regs.beshcoord,   mga_mmio_base + BESHCOORD);
  228. writel( regs.beshiscal,   mga_mmio_base + BESHISCAL);
  229. writel( regs.beshsrcst,   mga_mmio_base + BESHSRCST);
  230. writel( regs.beshsrcend,  mga_mmio_base + BESHSRCEND);
  231. writel( regs.beshsrclst,  mga_mmio_base + BESHSRCLST);
  232. writel( regs.besvcoord,   mga_mmio_base + BESVCOORD);
  233. writel( regs.besviscal,   mga_mmio_base + BESVISCAL);
  234. writel( regs.besv1srclst, mga_mmio_base + BESV1SRCLST);
  235. writel( regs.besv1wght,   mga_mmio_base + BESV1WGHT);
  236. //update the registers somewhere between 1 and 2 frames from now.
  237. writel( regs.besglobctl + ((readl(mga_mmio_base + VCOUNT)+2)<<16),
  238. mga_mmio_base + BESGLOBCTL);
  239. printk("mga_vid: wrote BES registersn");
  240. printk("mga_vid: BESCTL = 0x%08xn",
  241. readl(mga_mmio_base + BESCTL));
  242. printk("mga_vid: BESGLOBCTL = 0x%08xn",
  243. readl(mga_mmio_base + BESGLOBCTL));
  244. printk("mga_vid: BESSTATUS= 0x%08xn",
  245. readl(mga_mmio_base + BESSTATUS));
  246. //FIXME remove
  247. printk("besa1org = %08lxn",regs.besa1org);
  248. printk("besa1corg= %08lxn",regs.besa1corg);
  249. printk("besa1c3org= %08lxn",regs.besa1c3org);
  250. //FIXME remove
  251. }
  252. static int mga_vid_set_config(mga_vid_config_t *config)
  253. {
  254. int x, y, sw, sh, dw, dh;
  255. int besleft, bestop, ifactor, ofsleft, ofstop, baseadrofs, weight, weights;
  256. x = config->x_org;
  257. y = config->y_org;
  258. sw = config->src_width;
  259. sh = config->src_height;
  260. dw = config->dest_width;
  261. dh = config->dest_height;
  262. printk("mga_vid: Setting up a %dx%d+%d+%d video window (src %dx%d)n",
  263.        dw, dh, x, y, sw, sh);
  264. //FIXME check that window is valid and inside desktop
  265. //FIXME figure out a better way to allocate memory on card
  266. //allocate 2 megs
  267. //mga_src_base = mga_mem_base + (MGA_VIDMEM_SIZE-2) * 0x100000;
  268. mga_src_base = (MGA_VIDMEM_SIZE-2) * 0x100000;
  269. //Setup the BES registers for a three plane 4:2:0 video source 
  270. //BES enabled, even start polarity, filtering enabled, chroma upsampling
  271. //enabled, 420 mode enabled, dither enabled, mirror disabled, b/w
  272. //disabled, blanking enabled, software field select, buffer a1 displayed
  273. regs.besctl = 1 + (1<<10) + (1<<11) + (1<<16) + (1<<17) + (1<<18); 
  274. if(is_g400)
  275. {
  276. //zoom disabled, zoom filter disabled, 420 3 plane format, proc amp
  277. //disabled, rgb mode disabled 
  278. regs.besglobctl = (1<<5);
  279. }
  280. else
  281. {
  282. //zoom disabled, zoom filter disabled, Cb samples in 0246, Cr
  283. //in 1357, BES register update on besvcnt
  284. regs.besglobctl = 0;
  285. }
  286. //Disable contrast and brightness control
  287. regs.beslumactl = 0x80<<0;
  288. //Setup destination window boundaries
  289. besleft = x > 0 ? x : 0;
  290. bestop = y > 0 ? y : 0;
  291. regs.beshcoord = (besleft<<16) + (x + dw-1);
  292. regs.besvcoord = (bestop<<16) + (y + dh-1);
  293. //Setup source dimensions
  294. regs.beshsrclst  = (sw - 1) << 16;
  295. regs.bespitch = (sw + 31) & ~31 ; 
  296. //Setup horizontal scaling
  297. ifactor = ((sw-1)<<14)/(dw-1);
  298. ofsleft = besleft - x;
  299. regs.beshiscal = ifactor<<2;
  300. regs.beshsrcst = (ofsleft*ifactor)<<2;
  301. regs.beshsrcend = regs.beshsrcst + (((dw - ofsleft - 1) * ifactor) << 2);
  302. //Setup vertical scaling
  303. ifactor = ((sh-1)<<14)/(dh-1);
  304. ofstop = bestop - y;
  305. regs.besviscal = ifactor<<2;
  306. baseadrofs = ((ofstop*regs.besviscal)>>16)*regs.bespitch;
  307. regs.besa1org = (uint_32) mga_src_base + baseadrofs;
  308. if (is_g400) 
  309. baseadrofs = (((ofstop*regs.besviscal)/4)>>16)*regs.bespitch;
  310. else 
  311. baseadrofs = (((ofstop*regs.besviscal)/2)>>16)*regs.bespitch;
  312. regs.besa1corg = (uint_32) mga_src_base + regs.bespitch * sh + baseadrofs;
  313. regs.besa1c3org = regs.besa1corg + ((regs.bespitch * sh) / 4);
  314. weight = ofstop * (regs.besviscal >> 2);
  315. weights = weight < 0 ? 1 : 0;
  316. regs.besv1wght = (weights << 16) + ((weight & 0x3FFF) << 2);
  317. regs.besv1srclst = sh - 1 - (((ofstop * regs.besviscal) >> 16) & 0x03FF);
  318. mga_vid_write_regs();
  319. return 0;
  320. }
  321. static int mga_vid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  322. {
  323. switch(cmd) 
  324. {
  325. case MGA_VID_CONFIG:
  326. //FIXME remove
  327. printk("vcount = %dn",readl(mga_mmio_base + VCOUNT));
  328. printk("mga_mmio_base = %pn",mga_mmio_base);
  329. printk("mga_mem_base = %08lxn",mga_mem_base);
  330. //FIXME remove
  331. printk("mga_vid: Received configurationn");
  332. if(copy_from_user(&mga_config,(mga_vid_config_t*) arg,sizeof(mga_vid_config_t)))
  333. {
  334. printk("mga_vid: failed copy from userspacen");
  335. return(-EFAULT);
  336. }
  337. return mga_vid_set_config(&mga_config);
  338. break;
  339. case MGA_VID_ON:
  340. printk("mga_vid: Video ONn");
  341. vid_src_ready = 1;
  342. if(vid_overlay_on)
  343. {
  344. regs.besctl |= 1;
  345. mga_vid_write_regs();
  346. }
  347. break;
  348. case MGA_VID_OFF:
  349. printk("mga_vid: Video OFFn");
  350. vid_src_ready = 0;   
  351. regs.besctl &= ~1;
  352. mga_vid_write_regs();
  353. break;
  354.         default:
  355. printk("mga_vid: Invalid ioctln");
  356. return (-EINVAL);
  357. }
  358.        
  359. return 0;
  360. }
  361. static int mga_vid_find_card(void)
  362. {
  363. struct pci_dev *dev = NULL;
  364. if((dev = pci_find_device(PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400, NULL)))
  365. {
  366. is_g400 = 1;
  367. printk("mga_vid: Found MGA G400n");
  368. }
  369. else if((dev = pci_find_device(PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, NULL)))
  370. {
  371. is_g400 = 0;
  372. printk("mga_vid: Found MGA G200 AGPn");
  373. }
  374. else if((dev = pci_find_device(PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, NULL)))
  375. {
  376. is_g400 = 0;
  377. printk("mga_vid: Found MGA G200 PCIn");
  378. }
  379. else
  380. {
  381. printk("mga_vid: No supported cards foundn");
  382. return FALSE;   
  383. }
  384. pci_dev = dev;
  385. #if LINUX_VERSION_CODE >= 0x020300
  386. mga_mmio_base = ioremap_nocache(dev->resource[1].start,0x4000);
  387. mga_mem_base =  dev->resource[0].start;
  388. #else
  389. mga_mmio_base = ioremap_nocache(dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK,0x4000);
  390. mga_mem_base =  dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
  391. #endif
  392. printk("MMIO at 0x%pn", mga_mmio_base);
  393. printk("Frame at 0x%08lXn", mga_mem_base);
  394. return TRUE;
  395. }
  396. static ssize_t mga_vid_read(struct file *file, char *buf, size_t count, loff_t *ppos)
  397. {
  398. return -EINVAL;
  399. }
  400. static ssize_t mga_vid_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
  401. {
  402. return -EINVAL;
  403. }
  404. static int mga_vid_mmap(struct file *file, struct vm_area_struct *vma)
  405. {
  406. printk("mga_vid: mapping video memory into userspacen");
  407. if(remap_page_range(vma->vm_start, mga_mem_base + (MGA_VIDMEM_SIZE-2) * 0x100000,
  408.  vma->vm_end - vma->vm_start, vma->vm_page_prot)) 
  409. {
  410. printk("mga_vid: error mapping video memoryn");
  411. return(-EAGAIN);
  412. }
  413. return(0);
  414. }
  415. static int mga_vid_release(struct inode *inode, struct file *file)
  416. {
  417. //Close the window just in case
  418. vid_src_ready = 0;   
  419. regs.besctl &= ~1;
  420. mga_vid_write_regs();
  421. mga_vid_in_use = 0;
  422. //FIXME put back in!
  423. //MOD_DEC_USE_COUNT;
  424. return 0;
  425. }
  426. static long long mga_vid_lseek(struct file *file, long long offset, int origin)
  427. {
  428. return -ESPIPE;
  429. }  
  430. static int mga_vid_open(struct inode *inode, struct file *file)
  431. {
  432. int minor = MINOR(inode->i_rdev);
  433. if(minor != 0)
  434.  return(-ENXIO);
  435. if(mga_vid_in_use == 1) 
  436. return(-EBUSY);
  437. mga_vid_in_use = 1;
  438. //FIXME turn me back on!
  439. //MOD_INC_USE_COUNT;
  440. return(0);
  441. }
  442. static struct file_operations mga_vid_fops =
  443. {
  444. mga_vid_lseek,
  445. mga_vid_read,
  446. mga_vid_write,
  447. NULL,
  448. NULL,
  449. mga_vid_ioctl,
  450. mga_vid_mmap,
  451. mga_vid_open,
  452. NULL,
  453. mga_vid_release
  454. };
  455. static long mga_v4l_read(struct video_device *v, char *buf, unsigned long count, 
  456. int noblock)
  457. {
  458. return -EINVAL;
  459. }
  460. static long mga_v4l_write(struct video_device *v, const char *buf, unsigned long count, int noblock)
  461. {
  462. return -EINVAL;
  463. }
  464. static int mga_v4l_open(struct video_device *dev, int mode)
  465. {
  466. MOD_INC_USE_COUNT;
  467. return 0;
  468. }
  469. static void mga_v4l_close(struct video_device *dev)
  470. {
  471. regs.besctl &= ~1;
  472. mga_vid_write_regs();
  473. vid_overlay_on = 0;
  474. MOD_DEC_USE_COUNT;
  475. return;
  476. }
  477. static int mga_v4l_init_done(struct video_device *dev)
  478. {
  479. return 0;
  480. }
  481. static int mga_v4l_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
  482. {
  483. switch(cmd)
  484. {
  485. case VIDIOCGCAP:
  486. {
  487. struct video_capability b;
  488. strcpy(b.name, "Matrox G200/400");
  489. b.type = VID_TYPE_SCALES|VID_TYPE_OVERLAY|VID_TYPE_CHROMAKEY;
  490. b.channels = 0;
  491. b.audios = 0;
  492. b.maxwidth = 1024; /* GUESS ?? */
  493. b.maxheight = 768;
  494. b.minwidth = 32;
  495. b.minheight = 16; /* GUESS ?? */
  496. if(copy_to_user(arg,&b,sizeof(b)))
  497. return -EFAULT;
  498. return 0;
  499. }
  500. case VIDIOCGPICT:
  501. {
  502. /*
  503.  * Default values.. if we can change this we
  504.  * can add the feature later
  505.  */
  506. struct video_picture vp;
  507. vp.brightness = 0x8000;
  508. vp.hue = 0x8000;
  509. vp.colour = 0x8000;
  510. vp.whiteness = 0x8000;
  511. vp.depth = 8;
  512. /* Format is a guess */
  513. vp.palette = VIDEO_PALETTE_YUV420P;
  514. if(copy_to_user(arg, &vp, sizeof(vp)))
  515. return -EFAULT;
  516. return 0;
  517. }
  518. case VIDIOCSPICT:
  519. {
  520. return -EINVAL;
  521. }
  522. case VIDIOCSWIN:
  523. {
  524. struct video_window vw;
  525. if(copy_from_user(&vw, arg, sizeof(vw)))
  526. return -EFAULT;
  527. if(vw.x <0 || vw.y <0 || vw.width < 32 
  528. || vw.height < 16)
  529. return -EINVAL;
  530. memcpy(&mga_win, &vw, sizeof(mga_win));
  531. mga_config.x_org = vw.x;
  532. mga_config.y_org = vw.y;
  533. mga_config.dest_width = vw.width;
  534. mga_config.dest_height = vw.height;
  535. /* 
  536.  * May have to add 
  537.  *
  538.  * #define VIDEO_WINDOW_CHROMAKEY 16 
  539.  *
  540.  * to <linux/videodev.h> 
  541.  */
  542. //add it here for now
  543. #define VIDEO_WINDOW_CHROMAKEY 16 
  544. if (vw.flags & VIDEO_WINDOW_CHROMAKEY)
  545. mga_config.colkey_on = 1;
  546. else 
  547. mga_config.colkey_on = 0;
  548. mga_config.colkey_red   = (vw.chromakey >> 24) & 0xFF;
  549. mga_config.colkey_green = (vw.chromakey >> 16) & 0xFF;
  550. mga_config.colkey_blue  = (vw.chromakey >> 8)  & 0xFF;
  551. mga_vid_set_config(&mga_config);
  552. return 0;
  553. }
  554. case VIDIOCGWIN:
  555. {
  556. if(copy_to_user(arg, &mga_win, sizeof(mga_win)))
  557. return -EFAULT;
  558. return 0;
  559. }
  560. case VIDIOCCAPTURE:
  561. {
  562. int v;
  563. if(copy_from_user(&v, arg, sizeof(v)))
  564. return -EFAULT;
  565. vid_overlay_on = v;
  566. if(vid_overlay_on && vid_src_ready)
  567. {
  568. regs.besctl |= 1;
  569. mga_vid_write_regs();
  570. }
  571. else
  572. {
  573. regs.besctl &= ~1;
  574. mga_vid_write_regs();
  575. }
  576. return 0;
  577. }
  578. default:
  579. return -ENOIOCTLCMD;
  580. }
  581. }
  582. static struct video_device mga_v4l_dev =
  583. {
  584. "Matrox G200/G400",
  585. VID_TYPE_CAPTURE,
  586. VID_HARDWARE_BT848, /* This is a lie for now */
  587. mga_v4l_open,
  588. mga_v4l_close,
  589. mga_v4l_read,
  590. mga_v4l_write,
  591. NULL,
  592. mga_v4l_ioctl,
  593. NULL,
  594. mga_v4l_init_done,
  595. NULL,
  596. 0,
  597. 0
  598. };
  599. /* 
  600.  * Main Initialization Function 
  601.  */
  602. static int mga_vid_initialize(void)
  603. {
  604. mga_vid_in_use = 0;
  605. printk( "Matrox MGA G200/G400 YUV Video interface v0.01 (c) Aaron Holtzman n");
  606. if(register_chrdev(MGA_VID_MAJOR, "mga_vid", &mga_vid_fops))
  607. {
  608. printk("mga_vid: unable to get major: %dn", MGA_VID_MAJOR);
  609. return -EIO;
  610. }
  611. if (!mga_vid_find_card())
  612. {
  613. printk("mga_vid: no supported devices foundn");
  614. unregister_chrdev(MGA_VID_MAJOR, "mga_vid");
  615. return -EINVAL;
  616. }
  617. if (video_register_device(&mga_v4l_dev, VFL_TYPE_GRABBER)<0)
  618. {
  619. printk("mga_vid: unable to register.n");
  620. unregister_chrdev(MGA_VID_MAJOR, "mga_vid");
  621. if(mga_mmio_base)
  622. iounmap(mga_mmio_base);
  623. mga_mmio_base = 0;
  624. return -EINVAL;
  625. }
  626. return(0);
  627. }
  628. int init_module(void)
  629. {
  630.    return mga_vid_initialize();
  631. }
  632. void cleanup_module(void)
  633. {
  634. video_unregister_device(&mga_v4l_dev);
  635. if(mga_mmio_base)
  636. iounmap(mga_mmio_base);
  637. //FIXME turn off BES
  638. printk("mga_vid: Cleaning up modulen");
  639. unregister_chrdev(MGA_VID_MAJOR, "mga_vid");
  640. }