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

DVD

开发平台:

Unix_Linux

  1. /*
  2.  * Video Capture Driver ( Video for Linux 1/2 )
  3.  * for the Matrox Marvel G200 and Rainbow Runner-G series
  4.  *
  5.  * This module is an interface to the G100 and G200 video extension
  6.  * registers.  
  7.  *
  8.  * Copyright (C) 1999  Ryan Drake <stiletto@mediaone.net>
  9.  *
  10.  * This program is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU General Public License
  12.  * as published by the Free Software Foundation; either version 2
  13.  * of the License, or (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  23.  *
  24.  *
  25.  *****************************************************************************
  26.  * Version History:
  27.  * V1.0 Ryan Drake         Initial version by Ryan Drake
  28.  * V1.1 Gerard v.d. Horst  Activated the backend scaler
  29.  */
  30. #ifndef __KERNEL__
  31. #define __KERNEL__
  32. #endif
  33. #ifndef MODULE
  34. #define MODULE
  35. #endif
  36. #include <linux/module.h>
  37. #include <linux/delay.h>
  38. #include <linux/errno.h>
  39. #include <linux/kernel.h>
  40. #include <linux/malloc.h>
  41. #include <linux/poll.h>
  42. #include <asm/io.h>
  43. #include <linux/pci.h>
  44. #include <linux/interrupt.h>
  45. #include "mgavideo.h"
  46. #include "tuner.h"
  47. #include "msp3400.h"
  48. #include "ks0127.h"
  49. #include "zr36060.h"
  50. #define dprintk     if (debug) printk
  51. static int debug = 0; /* insmod parameter */
  52. static int memsize = 8192 * 1024;
  53. #if LINUX_VERSION_CODE >= 0x020100
  54. MODULE_PARM(debug,"i");
  55. MODULE_PARM(memsize,"i");
  56. #endif
  57. /* i2c registers */
  58. #define PALWTADD        0x3c00
  59. #define X_DATAREG       0x3c0a
  60. #define XMISCCTRL       0x1e
  61. #define XGENIOCTRL      0x2a
  62. #define XGENIODATA      0x2b
  63. #define XKEYOPMODE      0x51
  64. #define XCOLMSK0RED     0x52
  65. #define XCOLMSK0GREEN   0x53
  66. #define XCOLMSK0BLUE    0x54
  67. #define XCOLKEY0RED     0x55
  68. #define XCOLKEY0GREEN   0x56
  69. #define XCOLKEY0BLUE    0x57
  70. #define SDA             0x10
  71. #define SCL             0x20
  72. #define I2C_DELAY       10
  73. /****************************************************************************
  74. * raw register access : these routines directly interact with the mga's
  75. *                       control aperature.  must not be called until after
  76. *                       the board's pci memory has been mapped.
  77. ****************************************************************************/
  78. static u32 _mgaread( struct mga_dev* mga, u32 reg )
  79. {
  80.         return readl( mga->ctrl + reg );
  81. }
  82. static u8 _mgareadb(struct mga_dev* mga, u32 reg )
  83. {
  84.         return readb(mga->ctrl + reg );
  85. }
  86. #ifdef NEVER
  87. static u16 _mgareadw(struct mga_dev* mga, u32 reg )
  88. {
  89.         return readw(mga->ctrl + reg );
  90. }
  91. #endif
  92. static void _mgawrite( struct mga_dev* mga, u32 reg, u32 data )
  93. {
  94.         writel( data, mga->ctrl + reg );
  95. }
  96. static void _mgawriteb( struct mga_dev* mga, u32 reg, u32 data )
  97. {
  98.         writeb( data, mga->ctrl + reg );
  99. }
  100. static void _mgawritew( struct mga_dev* mga, u32 reg, u32 data )
  101. {
  102.         writeb( data, mga->ctrl + reg );
  103. }
  104. /****************************************************************************
  105.  * Codec Interface      *
  106.  ****************************************************************************/
  107. /* Notes: 
  108.    This interface is made to work with the Zoran DVD Codec. More specifically it
  109.    implements 8 bit VMI protocol A, with a big endian target chip.
  110.    Tell me if it works with the ZR36060, or what needs to be configurable (byte order, bus size ?)
  111.    It also uses a fixed 128Kb buffer size.
  112.    There is room for improvements: 
  113.     1. if the previous command is a write we can concatenate the datas instead of wasting 8 bytes
  114.        for each write command
  115.     2. the command buffer is only 512 bytes wide. We can have on in kernel memory and only
  116.        write the content on the MGA framebuffer at execute time. This could speed up memory access,
  117.        and provide a solution that doesn't change the content of the framebuffer, as we don't have
  118.        a reserved buffer yet (X fb memory management stuff to the rescue...)
  119.  */
  120. /*
  121.  * CODECCTL fields and commands
  122.  */
  123. #define codecen 0x0001          /* CODEC enable, invert to disable */
  124. #define codecmode 0x0002        /* CODEC l33 mode, invert for VMI mode */
  125. #define cmdexectrig 0x0004      /* command execution trigger, invert to prevent execution */
  126. #define codecdatain 0x0008      /* compression, invert for decompression */
  127. #define vmimode 0x0010          /* VMI mode B, invert for mode A */
  128. #define stopcodec 0x0020        /* stop after current field, invert to not stop */
  129. #define codectransen 0x0040     /* enable transfer, invert to disable */
  130. #define CODEC_CMD(count, pause, stop, addr, read) ( (count) | ((pause) << 8) | ((stop) << 9) | ((addr) << 10) | ((read) << 15) )
  131. #define CODEC_WRITE(addr, byte) ( ((addr) << 8) | (byte) )
  132. #define RESET_CODEC_CMD_PTR  mga->codeccmd   = mga->codecaddr + 0x0020000
  133. #define RESET_CODEC_DATA_PTR mga->codecdata  = mga->codecaddr + 0x0020200
  134. /* Resets the codec interface to the IDLE state */
  135. void codec_reset(struct mga_dev *mga) { 
  136. writel(VI_CMDCMPL, mga->ctrl + VICLEAR);
  137. writeb(0, mga->ctrl + CODECCTL);
  138. /* I repeat it twice per p. 4-110 of the G_4_00 HB */
  139. writeb(codecen, mga->ctrl + CODECCTL);
  140. writeb(codecen, mga->ctrl + CODECCTL);
  141. /* pulse recovery width (only usefull during bistream transfer
  142.    if I understand correctly p.46 of the Handbook
  143.    but we program the register anyway, as it belongs to 
  144.    the IDLE procedure referenced in the G400 manual */
  145. writeb((0<<4), mga->ctrl + CODECCTL + 1);
  146. RESET_CODEC_CMD_PTR;
  147. }
  148. /* Plays with the MISCCTL part of the codec interface
  149.    Used to reset the actual CODEC chip connected to the MISC lines
  150.    of the interface.
  151.  */
  152. void codec_miscctl(struct mga_dev *mga, u8 and, u8 or) {
  153.   /* we must be in IDLE (or COMP/DECOMP) for this to work p. 4-89)
  154.      p. 4-92 states that MISC[2] is connected to EOI (?) when the CODEC Interface
  155.      is enabled. So it seems that we can bang on these 2 bits too... */
  156.   codec_reset(mga);
  157.   writeb((readb(mga->ctrl + CODECMISCCTL) & and) | or, mga->ctrl + CODECMISCCTL);
  158. }
  159. void mga_extrst(struct mga_dev *mga, u8 activate) {
  160.   u8 prev = readb(mga->ctrl + RST);
  161.   if (activate)
  162.     writeb(prev | 2, mga->ctrl + RST);
  163.   else
  164.     writeb(prev & ~2, mga->ctrl + RST);
  165. }
  166. int codec_miscctl_func1(struct mga_dev *mga, u8 param) {
  167.   writeb(readb(mga->ctrl + CODECCTL) | codecen, mga->ctrl + CODECCTL);
  168.   writeb(readb(mga->ctrl + CODECMISCCTL) & ~param, mga->ctrl + CODECMISCCTL);
  169.   writeb(readb(mga->ctrl + CODECCTL) & ~codecen, mga->ctrl + CODECCTL);
  170.   writeb(XGENIOCTRL, mga->ctrl + PALWTADD);
  171.   writeb(readb(mga->ctrl + X_DATAREG) & ~0x40, mga->ctrl + X_DATAREG);
  172.   writeb(XGENIODATA, mga->ctrl + PALWTADD);
  173.   if (readb(mga->ctrl + X_DATAREG) & 0x40)
  174.     return 0;
  175.   else
  176.     return 1;
  177. }
  178. int codec_miscctl_func2(struct mga_dev *mga) {
  179.    writeb(readb(mga->ctrl + CODECCTL) | codecen, mga->ctrl + CODECCTL);
  180.    writeb(readb(mga->ctrl + CODECMISCCTL) |  0x40, mga->ctrl + CODECMISCCTL);
  181.    writeb(readb(mga->ctrl + CODECMISCCTL) & ~0x40, mga->ctrl + CODECMISCCTL);
  182.    writeb(readb(mga->ctrl + CODECCTL) & ~codecen, mga->ctrl + CODECCTL);
  183.    return 1;
  184. }
  185. int codec_I34_reset(struct mga_dev *mga) {
  186.   codec_miscctl(mga, 0x00, 0x00);
  187.   codec_miscctl(mga, 0x00, 0x03);
  188.   codec_miscctl(mga, 0x00, 0x03);
  189.   codec_miscctl(mga, ~0x0f, 0x07);
  190.   mdelay(10);
  191.   codec_miscctl(mga, ~0x0f, 0x03);
  192.   mdelay(1);
  193.   codec_miscctl(mga, ~0x0f, 0x07);
  194.   codec_miscctl(mga, ~0x0f, 0x07);
  195.   mdelay(100);
  196.   codec_miscctl(mga, ~0x0f, 0x0f);
  197.   mdelay(1);
  198.   codec_miscctl(mga, ~0x0f, 0x07);
  199.   mdelay(200);
  200.   return 0;
  201. /* Adds a READ command to the command buffer */
  202. void codec_read(struct mga_dev *mga, u8 reg) {
  203. /* duplicate reads because we're talking on an 8 bit bus */
  204.         writel(CODEC_CMD(2, 0, 0, reg, 1), mga->codeccmd);
  205. writel(0, mga->codeccmd+4);
  206. mga->codeccmd += 8;
  207. }
  208. /* Adds a WRITE command to the command buffer */
  209. void codec_write(struct mga_dev *mga, u8 reg, u16 data) {
  210. u8 b;
  211. /* per p. 44 of the Zoran HB : */
  212. /* 2 consecutive byte accesses to the same address */
  213. writel(CODEC_CMD(2, 0, 0, 0, 0), mga->codeccmd);
  214. writel(0, mga->codeccmd+4);
  215. mga->codeccmd += 8;
  216. /*#ifdef __LITTLE_ENDIAN
  217. b = (data>>8) & 0xFF;
  218.         writew(CODEC_WRITE(reg, b), mga->codeccmd);
  219.         b = data & 0xFF;
  220.         writew(CODEC_WRITE(reg, b), mga->codeccmd+2);
  221. #else
  222. */
  223. /* m.s. byte first */
  224. b = data & 0xFF;
  225. writew(CODEC_WRITE(reg, b), mga->codeccmd);
  226. b = (data>>8) & 0xFF;
  227. writew(CODEC_WRITE(reg, b), mga->codeccmd+2);
  228. writel(0, mga->codeccmd+4);
  229. mga->codeccmd += 8;
  230. // watch out the command buffer : we only have 512 bytes to play with !
  231. if ((mga->codeccmd - mga->codecaddr - 0x0020000) > 500) {
  232. dprintk("mgavideo: flushing codec command buffer...n");
  233. codec_exec(mga);
  234. }
  235. }
  236. /* Triggers execution of the command buffer
  237.    We automatically add a dummy read command with the STOP bit enabled
  238.    to terminate the instruction chain
  239. */
  240. void codec_exec(struct mga_dev *mga) {
  241. /* push a dummy command with the STOP bit enabled */
  242. writel(CODEC_CMD(2, 0, 1, 0x7, 1), mga->codeccmd);
  243. writel(0, mga->codeccmd+4);
  244. mga->codeccmd += 8;
  245. /* p. 3-68 of the MGA HandBook : it's not mentionned but we need not shift the addr
  246.    by 3 bits. Instead it's placed directly from bit 0 onward, but bits 0-7 are nulls
  247.    because we are Kb aligned */
  248. writel(((mga->codecaddr - (u32)mga->fb) & ~0x03), mga->ctrl + CODECADDR);
  249. RESET_CODEC_DATA_PTR;
  250. writel(0, mga->codecdata); writel(0, mga->codecdata+4);
  251. writel(0, mga->codecdata+8); writel(0, mga->codecdata+12);
  252. writel(0, mga->codecdata+16); writel(0, mga->codecdata+20);
  253. /* WARNING: it's the right combination : I've been blocked by those 2 bits for too long ! */
  254. codec_reset(mga);
  255. writeb(codecen | cmdexectrig, mga->ctrl + CODECCTL);
  256. /* give time to the Codec Interface do actually do its job */
  257. udelay(6);
  258. // if (!(_mgaread(mga, VSTATUS) & 0x02)) {
  259. // dprintk("mgavideo: warning no cmdcmpl after codec command...n");
  260. // }
  261. //    else {
  262. // _mgawrite(mga, VICLEAR, 0x02);
  263. // }
  264. }
  265. /* Retrieves a word from the data buffer */
  266. u16 codec_getw(struct mga_dev *mga) {
  267. u16 data;
  268. data = readw(mga->codecdata);
  269. /*#ifdef __LITTLE_ENDIAN
  270.   data = __swab16(data);
  271.   #endif
  272. */
  273. #ifdef BYTEORDERHACK
  274. if (mga->little_endian_codec)
  275. data = __swab16(data);
  276. #endif
  277. mga->codecdata += 8;
  278. return data;
  279. }
  280. /* dumps the content of the codec interface buffers */
  281. void dump_codec_cmdbuffer(struct mga_dev *mga) {
  282. RESET_CODEC_CMD_PTR;
  283. dprintk("mgavideo: Command buffer:n");
  284. dprintk("mgavideo: 0x%8.8x%8.8xn", readl(mga->codeccmd+4), readl(mga->codeccmd));
  285. dprintk("mgavideo: 0x%8.8x%8.8xn", readl(mga->codeccmd+12), readl(mga->codeccmd+8));
  286. dprintk("mgavideo: 0x%8.8x%8.8xn", readl(mga->codeccmd+20), readl(mga->codeccmd+16));
  287. dprintk("mgavideo: 0x%8.8x%8.8xn", readl(mga->codeccmd+28), readl(mga->codeccmd+24));
  288. dprintk("mgavideo: 0x%8.8x%8.8xn", readl(mga->codeccmd+36), readl(mga->codeccmd+32));
  289. dprintk("mgavideo: Data buffer:n");
  290. dprintk("mgavideo: 0x%8.8x%8.8xn", readl(mga->codecdata+4), readl(mga->codecdata));
  291. dprintk("mgavideo: 0x%8.8x%8.8xn", readl(mga->codecdata+12), readl(mga->codecdata+8));
  292. dprintk("mgavideo: 0x%8.8x%8.8xn", readl(mga->codecdata+20), readl(mga->codecdata+16));
  293. dprintk("mgavideo: 0x%8.8x%8.8xn", readl(mga->codecdata+28), readl(mga->codecdata+24));
  294. dprintk("mgavideo: 0x%8.8x%8.8xn", readl(mga->codecdata+36), readl(mga->codecdata+32));
  295. }
  296. static void 
  297. mgacodec_and_or_codecctl(struct codec *codec, u16 and, u16 or)
  298. {
  299. int codecctl;
  300. struct mga_dev *mga;
  301. mga = codec->private;
  302. codecctl = (mga->codecctl_shadow & and) | or;
  303. mga->codecctl_shadow = codecctl;
  304. _mgawritew(mga, CODECCTL, codecctl);
  305. }
  306. static void 
  307. mgacodec_and_or_codecmisc(struct codec *codec, u16 and, u16 or)
  308. {
  309. int codecmisc;
  310. struct mga_dev *mga;
  311. mga = codec->private;
  312. codecmisc = (mga->codecmisc_shadow & and) | or;
  313. mga->codecmisc_shadow = codecmisc;
  314. _mgawriteb(mga, CODECCTL+3, codecmisc);
  315. }
  316. static int
  317. mgacodec_execute_command(struct codec *codec)
  318. {
  319. int i;
  320. int status;
  321. struct mga_dev *mga;
  322. mga = codec->private;
  323. /* tell the system where memory buffer for zr36060 exists */
  324. _mgawrite(mga, CODECADDR, (mga->host_interface_base & ~0x03) | 0x01);
  325. if (mga->codecctl_shadow & VC_TRANSEN) {
  326. printk("wait for transfor to stopn");
  327. mgacodec_and_or_codecctl(codec, ~(VC_TRIG | VC_TRANSEN), 0);
  328. for(i = 1024 * 1024, status = _mgaread(mga, VSTATUS);
  329.     (status & VS_STALLED) == 0 && i--; 
  330.     status = _mgaread(mga, VSTATUS)) ;
  331. printk("transfer stoped status %x VS_STALLED %xn", status, VS_STALLED);
  332. }
  333. /* remove any pending command complete */
  334. _mgawriteb(mga, VICLEAR, VI_CMDCMPL);
  335. codec->state = ZR_WRITE_STATE;
  336. /* start codec command */
  337. mgacodec_and_or_codecctl(codec, ~0x00, VC_TRIG);
  338. /* wait for codec command to complete */
  339. for(i = 4096, status = _mgareadb(mga, VSTATUS);
  340. (status & VS_STALLED) == 0 && i--; 
  341. status = _mgareadb(mga, VSTATUS)) ;
  342. /* Ack the command complete interrupt */
  343. _mgawriteb(mga, VICLEAR, VI_CMDCMPL);
  344. codec->state = ZR_IDLE_STATE;
  345. mga->codec_offset = 0;
  346. if (status & VI_CMDCMPL)
  347. return 0;
  348. printk("mgavideo: no command complete on command 0x%x status 0x%xn", 
  349.        readw(mga->command_base), status);
  350. return 1;
  351. }
  352. static int
  353. mgacodec_read_memory(struct codec *codec, void *ptr, int mem, int size)
  354. {
  355. int last_high;
  356. int last_read;
  357. int last_exec;
  358. int i;
  359. int j;
  360. char *buffer;
  361. struct mga_dev *mga;
  362. mga = codec->private;
  363. buffer = ptr;
  364. last_high = -1;
  365. last_read = 0;
  366. last_exec = 0;
  367. dprintk("mgavideo: read %d bytes to memory %xn", size, mem);
  368. for(i=0; i < size; i++, mem++) {
  369. if (mga->codec_offset > (512 - 32)) {
  370. if (i > 0) {
  371. writew(0x8201 | (3 << 10), 
  372.        mga->command_base + last_read);
  373. }
  374. if (mgacodec_execute_command(codec)) {
  375. printk("mgavideo: Codec read buffer errorn");
  376. return -1;
  377. }
  378. for(j = last_exec; j < i; j++) {
  379. *buffer++ = readb(mga->read_base + 
  380.  (j - last_exec) * 8);
  381. }
  382. last_exec = i;
  383. }
  384. writew(0x0002, mga->command_base + mga->codec_offset);
  385. mga->codec_offset += 8;
  386. if (last_high != (mem >> 8)) {
  387. writew((mem >> 8) | 0x0100, 
  388. mga->command_base + mga->codec_offset);
  389. mga->codec_offset += 2;
  390. }
  391. writew((mem & 0xff) | 0x0200, 
  392. mga->command_base + mga->codec_offset);
  393. mga->codec_offset += 2;
  394. mga->codec_offset = (mga->codec_offset & ~7) + 8;
  395. writew(0x8001 | (3 << 10), 
  396. mga->command_base + mga->codec_offset);
  397. last_read = mga->codec_offset;
  398. mga->codec_offset += 8;
  399. }
  400. if (last_read > 0) {
  401. writew(0x8201 | (3 << 10), mga->command_base + last_read);
  402. }
  403. if (mgacodec_execute_command(codec)) {
  404. printk("mgavideo: Codec read buffer errorn");
  405. return -1;
  406. }
  407. for(i=last_exec; i < size; i++) {
  408. *buffer++ = readb(mga->read_base + (i - last_exec) * 8);
  409. }
  410. return 0;
  411. }
  412. static int
  413. mgacodec_write_memory(struct codec *codec, void *mem, int start_reg, int length)
  414. {
  415. int offset;
  416. int count;
  417. int last_high;
  418. char *buffer;
  419. struct mga_dev *mga;
  420. mga = codec->private;
  421. buffer = mem;
  422. offset = (int)mga->command_base + 8;
  423. count = 0;
  424. last_high = -1;
  425. dprintk("mgavideo writing %d bytes to memory %xn", 
  426. length, start_reg);
  427. while(length--) {
  428. if (last_high != (start_reg >> 8)) {
  429. last_high = start_reg >> 8;
  430. writew((start_reg >> 8) | 0x0100, offset);
  431. offset += 2;
  432. count++;
  433. }
  434.     
  435. writew((start_reg++ & 0xff) | 0x0200, offset);
  436. writew((*buffer++ & 0xff) | 0x0300, offset+2);
  437. offset+= 4;
  438. count += 2;
  439. if (count > 250) {
  440. writew(count | 0x200, mga->command_base);
  441. if (mgacodec_execute_command(codec)) {
  442. printk("mgavideo: Codec write buffer errorn");
  443. return -1;
  444. }
  445. offset = (int)mga->command_base + 8;
  446. count = 0;
  447. }
  448. }
  449. if (count) {
  450. writew(count | 0x200, mga->command_base);
  451. if (mgacodec_execute_command(codec)) {
  452. printk("mgavideo: Codec write buffer errorn");
  453. return -1;
  454. }
  455. }
  456. return 0;
  457. }
  458. static int
  459. mgacodec_zr6060_start(struct codec *codec)
  460. {
  461. struct mga_dev *mga;
  462. mga = codec->private;
  463. _mgawrite(mga, CODECHOSTPTR, 64 * 1024);
  464. mgacodec_and_or_codecctl(codec, 0x4f, 0x4b);
  465. return 0;
  466. }
  467. static int
  468. mgacodec_zr36060_reset(struct codec *codec) 
  469. {
  470. struct mga_dev *mga;
  471. mga = codec->private;
  472. /* reset the codec interface engine */
  473. mgacodec_and_or_codecctl(codec, 0x00, 0x00);
  474. mgacodec_and_or_codecctl(codec, 0x00, 0x03);
  475. mgacodec_and_or_codecctl(codec, 0x00, 0x03);
  476. /* pulse the reset line */
  477. mgacodec_and_or_codecmisc(codec, ~0x0f, 0x07);
  478. mdelay(10);
  479. mgacodec_and_or_codecmisc(codec, ~0x0f, 0x03);
  480. mdelay(1);
  481. mgacodec_and_or_codecmisc(codec, ~0x0f, 0x07);
  482. /* pulse the sleep line */
  483. mgacodec_and_or_codecmisc(codec, ~0x0f, 0x07);
  484. mdelay(100);
  485. mgacodec_and_or_codecmisc(codec, ~0x0f, 0x0f);
  486. mdelay(1);
  487. mgacodec_and_or_codecmisc(codec, ~0x0f, 0x07);
  488. mdelay(200);
  489. /* tell the system where memory buffer for zr36060 exists */
  490. _mgawrite(mga, CODECADDR, (mga->host_interface_base & ~0x03) | 0x01);
  491. return 0;
  492. }
  493. /****************************************************************************
  494. * mga i2c bus interface
  495. ****************************************************************************/
  496. static void _mgai2c_attach( struct i2c_bus* bus, int id )
  497. {
  498.         struct mga_dev* mga = (struct mga_dev*)bus->data;
  499.         dprintk( "mgavideo: i2c device attach: %dn", id );
  500.         switch( id )
  501.         {
  502.         case I2C_DRIVERID_MSP3400:
  503.                 mga->hasaudio = 1;
  504.                 break;
  505.         case I2C_DRIVERID_TUNER:
  506.                 mga->hastuner = 1;
  507.                 break;
  508.         case I2C_DRIVERID_KS0127:
  509.                 mga->hasdecoder = 1;
  510.                 break;
  511.         }
  512. }
  513. static void _mgai2c_detach( struct i2c_bus* bus, int id )
  514. {
  515.         struct mga_dev* mga = (struct mga_dev*)bus->data;
  516.         dprintk( "mgavideo: i2c device detach: %dn", id );
  517.         switch( id )
  518.         {
  519.         case I2C_DRIVERID_MSP3400:
  520.                 mga->hasaudio = 0;
  521.                 break;
  522.         case I2C_DRIVERID_TUNER:
  523.                 mga->hastuner = 0;
  524.                 break;
  525.         case I2C_DRIVERID_KS0127:
  526.                 mga->hasdecoder = 0;
  527.                 break;
  528.         }
  529. }
  530. static void _mgai2c_setlines( struct i2c_bus* bus, int ctrl, int data )
  531. {
  532.         struct mga_dev* mga = (struct mga_dev*)bus->data;
  533.         if( ctrl )
  534.         {
  535.         writeb( XGENIOCTRL, mga->ctrl + PALWTADD );
  536.         writeb( readb( mga->ctrl + X_DATAREG ) & ~SCL, mga->ctrl + X_DATAREG );
  537.         }
  538.         else
  539.         {
  540.         writeb( XGENIODATA, mga->ctrl + PALWTADD );
  541.         writeb( readb( mga->ctrl + X_DATAREG ) & ~SCL, mga->ctrl + X_DATAREG );
  542.         writeb( XGENIOCTRL, mga->ctrl + PALWTADD );
  543.         writeb( readb( mga->ctrl + X_DATAREG ) | SCL, mga->ctrl + X_DATAREG );
  544.         }
  545.         if( data )
  546.         {
  547.         writeb( XGENIOCTRL, mga->ctrl + PALWTADD );
  548.         writeb( readb( mga->ctrl + X_DATAREG ) & ~SDA, mga->ctrl + X_DATAREG );
  549.         }
  550.         else
  551.         {
  552.         writeb( XGENIODATA, mga->ctrl + PALWTADD );
  553.         writeb( readb( mga->ctrl + X_DATAREG ) & ~SDA, mga->ctrl + X_DATAREG );
  554.         writeb( XGENIOCTRL, mga->ctrl + PALWTADD );
  555.         writeb( readb( mga->ctrl + X_DATAREG ) | SDA, mga->ctrl + X_DATAREG );
  556.         }
  557.         udelay( I2C_DELAY );
  558. }
  559. static int _mgai2c_getdataline( struct i2c_bus* bus )
  560. {
  561.         struct mga_dev* mga = (struct mga_dev*)bus->data;
  562.         writeb( XGENIOCTRL, mga->ctrl + PALWTADD );
  563.         writeb( readb( mga->ctrl + X_DATAREG ) & ~SDA, mga->ctrl + X_DATAREG );
  564.         writeb( XGENIODATA, mga->ctrl + PALWTADD );
  565.         return ( readb( mga->ctrl + X_DATAREG ) & SDA )?1:0;
  566. }
  567. /****************************************************************************
  568. * private api : internal interface to the mga's video subsystem
  569. ****************************************************************************/
  570. /****************************************************************************
  571. * mgavideo api : public interface to the mga's video subsystem
  572. ****************************************************************************/
  573. /* component device control */
  574. void mgavideo_tuner( struct mga_dev* mga, unsigned int cmd, void* arg )
  575. {
  576.         if( mga == NULL )
  577.                 return;
  578.         if( mga->hastuner )
  579.                 i2c_control_device( &(mga->i2c), I2C_DRIVERID_TUNER, cmd, arg );
  580. }
  581. void mgavideo_audio( struct mga_dev* mga, unsigned int cmd, void* arg )
  582. {
  583.         if( mga == NULL )
  584.                 return;
  585.         if( mga->hasaudio )
  586.                 i2c_control_device( &(mga->i2c), I2C_DRIVERID_MSP3400, cmd, arg );
  587. }
  588. void mgavideo_decoder( struct mga_dev* mga, unsigned int cmd, void* arg )
  589. {
  590.         if( mga == NULL )
  591.                 return;
  592.         if( mga->hasdecoder )
  593.                 i2c_control_device( &(mga->i2c), I2C_DRIVERID_KS0127, cmd, arg );
  594. }
  595. void mgavideo_zr36060_reset(struct mga_dev* mga)
  596. {
  597.   // dbarth:
  598.   // is it still usefull to have that here. It creates a dependency with mgavideo
  599.   // and complicates module loading/unloading
  600.   // Please tell me
  601. #ifdef NEVER
  602. zr36060_attach(&mga->zr36060);
  603. #endif
  604. }
  605. int mgavideo_querycaps( struct mga_dev* mga )
  606. {
  607.         int caps = 0;
  608.         if( mga == NULL )
  609.                 return 0;
  610.         if( mga->hastuner )
  611.                 caps |= MGAVIDEO_HAS_TUNER;
  612.         if( mga->hasaudio )
  613.                 caps |= MGAVIDEO_HAS_AUDIO;
  614.         if( mga->hasdecoder )
  615.                 caps |= MGAVIDEO_HAS_DECODER;
  616.         return caps;
  617. }
  618. u8* mgavideo_lock_video( struct mga_dev* mga )
  619. {
  620.         mga->locked = mga->status;
  621.         if( mga->status & VS_FIELD ) {
  622.                 return mga->fb + mga->vin_addr1;
  623.         } else {
  624.                 return mga->fb + mga->vin_addr0;
  625.         }
  626. }
  627. void mgavideo_unlock_video( struct mga_dev* mga )
  628. {
  629.         mga->locked = 0;
  630. }
  631. static void _detect_tvt( struct mga_dev* mga )
  632. {
  633.         int msp, tuner_addr, tuner;
  634.         if( mga->hastuner && mga->hasaudio ) {
  635.                 mgavideo_tuner( mga, TUNER_GET_ADDRESS, &tuner_addr );
  636.                 mgavideo_audio( mga, MSP_GET_UNIT, &msp );
  637.                 tuner = TUNER_ABSENT;
  638.                 switch( tuner_addr ) {
  639.                 case 0xc0:
  640.                         /* Samsung MULTI PAL - unsupported by tuner.c? */
  641.                         break;
  642.                 case 0xc2:
  643.                         if( (msp&0xff) == 0x07 ) { /* Usa audio */
  644.                                 tuner = TUNER_PHILIPS_NTSC;
  645.                         } else {
  646.                         /* Samsung SECAM - unsupported by tuner.c? */
  647.                         }
  648.                         break;
  649.                 
  650.                 case 0xc4:
  651.                         tuner = TUNER_PHILIPS_PAL_I;
  652.                         break;
  653.                 case 0xc6:
  654.                         if( (msp&0xff) == 0x07 ) { /* Usa audio */
  655.                         /* Samsung NTSC - unsupported by tuner.c? */
  656.                         } else {
  657.                                 tuner = TUNER_PHILIPS_SECAM;
  658.                         }
  659.                 }
  660.                 
  661.                 mgavideo_tuner( mga, TUNER_SET_TYPE, &tuner );
  662.         }
  663. }
  664. /****************************************************************************
  665. * interrupt processing
  666. ****************************************************************************/
  667. static void mgavideo_vsync(struct mga_dev *mga)
  668. {
  669.         /* increment frame counter */
  670.         mga->grabbed++;
  671. /* We may have change the pitch or base address */
  672. if (mga->status & VS_FIELD) {
  673. /* program even field data */
  674. _mgawrite( mga, VINCTL0, ( VIN_ON | VBI_RAW | (mga->vinpitch >> 2) << 3) );
  675. } else {
  676. /* program odd field data */
  677. _mgawrite( mga, VINCTL1, ( VIN_ON | VBI_RAW | (mga->vinpitch >> 2) << 3) );
  678. }
  679. #ifdef NEVER
  680. zr36060_compress_image(&mga->zr36060);
  681. {
  682. struct timeval curr;
  683. do_gettimeofday(&curr);
  684. dprintk("mgavideo: interrupt status=%x  frames e=%d o=%d time: %d:%dn", mga->status, 
  685. mga->req_even, mga->req_odd, curr.tv_sec, curr.tv_usec);
  686. }
  687. #endif
  688.         
  689.         if( !(mga->locked & ( VS_VIDEO | VS_RAWVBI | VS_SLICEDVBI ) ) ) {
  690. /* if no video fields are locked, program the next window
  691.  * based on what window was just grabbed */
  692. #ifdef NEVER
  693. _mgawrite( mga, VINNEXTWIN, (mga->status&VS_FIELD)?0:1 );
  694. #else
  695. _mgawrite( mga, VINNEXTWIN, (mga->status&VS_FIELD)?1:0 );
  696. #endif
  697.                 /* queue bottom half if present, and requested */
  698.                 if( mga->tqnode_dpc.routine ) {
  699.                         if (( mga->req_even && !( mga->status & VS_FIELD ))
  700.                         ||  ( mga->req_odd  &&  ( mga->status & VS_FIELD ))) {
  701.                                 queue_task(&mga->tqnode_dpc, &tq_immediate);
  702.                                 mark_bh(IMMEDIATE_BH);
  703.                         } else {
  704. #ifdef NEVER
  705. printk("frame not wanted odd %d even %d status= %xn",
  706. mga->req_even, mga->req_odd, mga->status);
  707. #endif
  708. }
  709.                 }
  710.         } else {
  711.                 /* otherwise, program the next window based on what field
  712.                  * is locked */
  713. #ifdef NEVER
  714. _mgawrite( mga, VINNEXTWIN, (mga->status&VS_FIELD)?0:1 );
  715. #else
  716. _mgawrite( mga, VINNEXTWIN, (mga->status&VS_FIELD)?1:0 );
  717. #endif
  718. #ifdef NEVER
  719. printk("frame buffer lockedn");
  720. #endif
  721.         }
  722. }
  723. static void interrupt_hw(int irq, void *v, struct pt_regs *regs)
  724. {
  725.         struct mga_dev* mga = (struct mga_dev*)v;
  726.         if (mga == NULL)
  727.                 return;
  728.         /* read status register */
  729.         mga->status = _mgaread( mga, VSTATUS );
  730. if (mga->status & VI_IVSYNC)  {
  731. mgavideo_vsync(mga);
  732. _mgawrite( mga, VICLEAR, VI_IVSYNC );
  733. }
  734. if (mga->status & VI_CMDCMPL) {
  735. printk("mgavideo: command complete pendingn");
  736. #ifdef NEVER
  737. zr36060_interrupt(&mga->zr);
  738. _mgawrite( mga, VICLEAR, VI_CMDCMPL);
  739. #endif
  740. }
  741. if (mga->status & VI_BLVL) {
  742. printk("mgavideo: buffer level pendingn");
  743. _mgawrite( mga, VICLEAR, VI_BLVL);
  744. }
  745. if (mga->status & VI_EOI)  {
  746. printk("mgavideo: codec decompression end of image pendingn");
  747. _mgawrite( mga, VICLEAR, VI_EOI);
  748. }
  749. }
  750. /* enable interrupts */
  751. void mgavideo_ivsync_enable( struct mga_dev* mga, int en )
  752. {
  753.         u32 istat;
  754.         if( mga == NULL )
  755.                 return;
  756.         dprintk( "mgavideo: %sable IVSYNC interruptn", en?"en":"dis" );
  757.         _mgawrite( mga, VICLEAR, VI_IVSYNC );
  758.         istat = _mgaread( mga, VIEN );
  759.         _mgawrite( mga, VIEN, en?(istat|VI_IVSYNC):(istat&~VI_IVSYNC) );
  760. }
  761. /* register a routine to be called for each frame */
  762. void mgavideo_register_bh( struct mga_dev* mga, int req_even, int req_odd,
  763.                            void(*routine)(void*), void* data )
  764. {
  765.         mga->req_even = req_even;
  766.         mga->req_odd = req_odd;
  767.         mga->tqnode_dpc.next = NULL;
  768.         mga->tqnode_dpc.sync = 0;
  769.         mga->tqnode_dpc.routine = routine;
  770.         mga->tqnode_dpc.data = data;
  771. }
  772. /*
  773.  * reset the the hardware for dma cap for new size. Also need to
  774.  * update the ks0127 to scale for new size.
  775.  */
  776. void  mgavideo_set_dims(struct mga_dev *mga, int width, int height)
  777. {
  778. mgavideo_decoder( mga, KS0127_SET_WIDTH, &width);
  779. mga->vinpitch = width;
  780. #ifdef NEVER
  781. mgavideo_decoder( mga, KS0127_SET_HEIGHT, &height);
  782. #endif
  783. }
  784. /****************************************************************************
  785. * back-end scaler
  786. ****************************************************************************/
  787. void* mgavideo_get_base( struct mga_dev* mga )
  788. {
  789.         return mga->fb;
  790. }
  791. void mgavideo_set_window( struct mga_dev* mga, int x, int y, int w, int h )
  792. {
  793.         _mgawrite( mga, BESHCOORD, (x<<16) | (x+w-1) );
  794.         _mgawrite( mga, BESVCOORD, (y<<16) | (y+h-1) );
  795.         _mgawrite( mga, BESHISCAL, (_VINWID<<16) / w);
  796.         _mgawrite( mga, BESVISCAL, (_VINHGT<<16) / h);
  797. }
  798. void mgavideo_set_colorkey( struct mga_dev* mga, int r, int g, int b )
  799. {
  800.         /* Activate the colorkey mode */
  801.         writeb( XKEYOPMODE, mga->ctrl + PALWTADD );
  802.         writeb( 1, mga->ctrl + X_DATAREG );
  803.         writeb( XCOLMSK0RED, mga->ctrl + PALWTADD );
  804.         writeb( 0xff, mga->ctrl + X_DATAREG );
  805.         writeb( XCOLMSK0GREEN, mga->ctrl + PALWTADD );
  806.         writeb( 0xff, mga->ctrl + X_DATAREG );
  807.         writeb( XCOLMSK0BLUE, mga->ctrl + PALWTADD );
  808.         writeb( 0xff, mga->ctrl + X_DATAREG );
  809.         writeb( XCOLKEY0RED, mga->ctrl + PALWTADD );
  810.         writeb( r, mga->ctrl + X_DATAREG );
  811.         writeb( XCOLKEY0GREEN, mga->ctrl + PALWTADD );
  812.         writeb( g, mga->ctrl + X_DATAREG );
  813.         writeb( XCOLKEY0BLUE, mga->ctrl + PALWTADD );
  814.         writeb( b, mga->ctrl + X_DATAREG );
  815. }
  816. void mgavideo_set_overlay( struct mga_dev* mga )
  817. {
  818.         /* Activate the overlay mode */
  819.         writeb( XKEYOPMODE, mga->ctrl + PALWTADD );
  820.         writeb( 0, mga->ctrl + X_DATAREG );
  821. }
  822. void mgavideo_preview_enable( struct mga_dev* mga, int en )
  823. {
  824.         /* Activate scaler */
  825.         _mgawrite( mga, BESCTL, en?0x00000007:0x00000000 ); 
  826.         /* Activate automatic switching of windows
  827.          * This is for testing only
  828.         */
  829.         _mgawrite( mga, VINNEXTWIN, en?2:0 );
  830. }
  831. /****************************************************************************
  832. * initialization
  833. ****************************************************************************/
  834. static void _mgavideo_init( struct mga_dev* mga )
  835. {
  836.         writeb( XMISCCTRL, mga->ctrl + PALWTADD );
  837.         writeb( readb( mga->ctrl + X_DATAREG ) | 0x06, mga->ctrl + X_DATAREG );
  838.         /* detect tv-tuner */
  839.         _detect_tvt( mga );
  840.         /* enable video-in */
  841.         _mgawrite( mga, VINCTL, 0x0101ab01 );
  842.         /* just in case, clear video interrupt */
  843.         _mgawrite( mga, VICLEAR, VI_IVSYNC );
  844.         /* setup video window 0 */
  845.         _mgawrite( mga, VINCTL0, ( VIN_ON | VBI_RAW | (mga->vinpitch >> 2) << 3) );
  846.         _mgawrite( mga, VBIADDR0, mga->vbi_addr0);
  847.         _mgawrite( mga, VINADDR0, mga->vin_addr0);
  848.         /* setup video window 1 */
  849.         _mgawrite( mga, VINCTL1, ( VIN_ON | VBI_RAW | (mga->vinpitch >> 2) << 3) );
  850.         _mgawrite( mga, VBIADDR1, mga->vbi_addr1);
  851.         _mgawrite( mga, VINADDR1, mga->vin_addr1);
  852.         /* setup backend scaler */
  853.         _mgawrite( mga, BESPITCH, mga->vinpitch & (~3));
  854.         _mgawrite( mga, BESHSRCLST, (_VINWID-1)<<16 );
  855.         _mgawrite( mga, BESHSRCST, 0<<14 );
  856.         _mgawrite( mga, BESHSRCEND, (_VINWID * 4 -1)<<14 );
  857.         _mgawrite( mga, BESV1SRCLST, 255 );
  858.         _mgawrite( mga, BESV2SRCLST, 255 );
  859.         _mgawrite( mga, BESA1ORG, mga->vin_addr0 );
  860.         _mgawrite( mga, BESA2ORG, mga->vin_addr1 );
  861.         _mgawrite( mga, BESB1ORG, mga->vin_addr0 );
  862.         _mgawrite( mga, BESB2ORG, mga->vin_addr1 );
  863.         /* register interrupt routine */
  864.         if( mga->irq ) {
  865.                 if( request_irq( mga->irq, interrupt_hw, SA_SHIRQ,
  866.                                  mga->name, mga ) < 0 ) {
  867.                         dprintk( "mgavideo: Denied IRQ %dn", mga->irq );
  868.                         mga->irq_status = 0;
  869.                 } else {
  870.                         mga->irq_status = mga->irq;
  871.                 }
  872.         }
  873. }
  874. #define NBOARDS 4
  875. struct mga_dev mgavideo_dev[NBOARDS];
  876. /* HACK to get the MGA struct.
  877.    the 'mgavideo_get' routine cannot handle multiple use
  878.    of the same board anyway...
  879. */
  880. struct mga_dev* mgavideo_get_codec() {
  881.   if (&mgavideo_dev[0] != NULL)
  882.     return &mgavideo_dev[0];
  883.   else
  884.     return NULL;
  885. }
  886. /* find all mga adapters */
  887. struct mga_dev* mgavideo_get( void )
  888. {
  889.         int i;
  890.         struct mga_dev* mga;
  891.         for( i=0; i<NBOARDS; i++ )
  892.         {
  893.                 mga = &mgavideo_dev[i];
  894.                 if( !mga->inuse && (mga->ctrl != NULL) )
  895.                 {
  896.                         dprintk( "mgavideo: acquire video device %xn", i );
  897.                         mga->inuse++;
  898.                         MOD_INC_USE_COUNT;
  899.                         _mgavideo_init( mga );
  900.                        return mga;
  901.                 }
  902.         }
  903.         return NULL;
  904. }
  905. /* release a mga adapter that is not needed anymore */
  906. void mgavideo_release( struct mga_dev* mga )
  907. {
  908.         if( mga == NULL )
  909.                 return;
  910.         if( mga->ctrl )
  911.         {
  912.                 /* clear any pending interrupt */
  913.                 _mgawrite( mga, VICLEAR, VI_IVSYNC );
  914.                 /* disable video interrupt */
  915.                 _mgawrite( mga, VIEN, _mgaread( mga, VIEN ) & ~VI_IVSYNC );
  916.                 /* disable video-in */
  917.                 _mgawrite( mga, VINCTL, 0x0101ab00 );
  918.                 /* disable (temp) backend scaler */
  919.                 mgavideo_preview_enable( mga, 0 );
  920. /* Turn off the zr36060 */
  921. #ifdef NEVER
  922. zr36060_deattach(&mga->zr);
  923. #endif
  924.                 /* un-register isr */
  925.                 if( mga->irq_status ) {
  926.                         free_irq( mga->irq_status, mga );
  927.                         mga->irq_status = 0;
  928.                 }
  929.                 MOD_DEC_USE_COUNT;
  930.                 mga->inuse--;
  931.                 dprintk( "mgavideo: release video devicen" );
  932.                 printk( "mgavideo: grabbed %d total framesn", mga->grabbed );
  933.         }
  934. }
  935. /****************************************************************************
  936. * linux kernel module api
  937. ****************************************************************************/
  938. #ifdef MODULE
  939. int init_module( void )
  940. #else
  941. int mgavideo_init( void )
  942. #endif
  943. {
  944.         int found = 0;
  945.         struct pci_dev* dev;
  946.         struct mga_dev* mga;
  947.         u32 mem;
  948.         u32 addr = 0;
  949.         dprintk( "mgavideo: Looking for boards...n" );
  950.         /* find the next MGA G100 or G200 */
  951.         for( dev = pci_devices; dev != NULL; dev = dev->next )
  952.         {
  953.                 if (dev->class != PCI_CLASS_NOT_DEFINED_VGA &&
  954.                   ((dev->class) >> 16 != PCI_BASE_CLASS_DISPLAY))
  955.                         continue;
  956.                 if (PCI_FUNC(dev->devfn) != 0)
  957.                         continue;
  958.                 /* ignore non-mga adapters */
  959.                 if (dev->vendor != PCI_VENDOR_ID_MATROX)
  960.                         continue;
  961.                 /* ignore non-gseries adapters */
  962.                 if (dev->device != PCI_DEVICE_ID_MATROX_G200_PCI &&
  963.                     dev->device != PCI_DEVICE_ID_MATROX_G200_AGP &&
  964.                     dev->device != PCI_DEVICE_ID_MATROX_G100_MM &&
  965.                     dev->device != PCI_DEVICE_ID_MATROX_G100_AGP)
  966.                         continue;
  967.                 /* the device is cool. set up a context for it */
  968.                 mga = &mgavideo_dev[found];
  969.                 memset( mga, 0, sizeof( *mga ) );
  970.                 mga->device = dev->device;
  971.                 mga->inuse = 0;
  972.                 mga->irq = dev->irq;
  973.          dprintk( "mgavideo: mapping fb memory...n" );
  974.                 /* read and map the frame buffer and control aperture */
  975.                 addr = dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
  976.                 mga->fb = ioremap( addr, 0x800000 );
  977.          dprintk( "mgavideo: mapping ctrl memory...n" );
  978.                 addr = dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK;
  979.                 mga->ctrl = ioremap( addr, 0x4000 );
  980.          dprintk( "mgavideo: Okn" );
  981.                 /* setup address for video in memory */
  982.                 mem = memsize - 1l;
  983.                 mem  = (mem - _VIN_WINDOW) & VINADDRx_MASK;
  984.                 mga->vin_addr0 = mem;
  985.                 mem  = (mem - _VIN_WINDOW) & VINADDRx_MASK;
  986.                 mga->vin_addr1 = mem;
  987.                 mem  = (mem - _VBI_WINDOW) & VBIADDRx_MASK;
  988.                 mga->vbi_addr0 =  mem;
  989.                 mem  = (mem - _VBI_WINDOW) & VBIADDRx_MASK;
  990.                 mga->vbi_addr1 = mem;
  991. /* init memory for zr36060 */
  992. mem = (mem - (257 * 1024)) & ~0x3ff;
  993. mga->host_interface_base = mem;
  994. mga->interface_base = (u8 *)(mga->fb) + mem;
  995. mga->command_base = (u8 *)(mga->fb) + (mem + 256 * 1024);
  996. mga->read_base = mga->command_base + 512;
  997. mga->codec_offset = 0;
  998. /* Default pitch for mga */
  999. mga->vinpitch = 704;
  1000. mga->vin_field = _VIN_FIELD_EVEN;
  1001. /* fill in zr36060 register address */
  1002. mga->zr36060.codec_id = ZR36060_ID;
  1003. mga->zr36060.private = mga;
  1004. mga->zr36060.memory_size = 8;
  1005. mga->zr36060.codec_read_memory = mgacodec_read_memory;
  1006. mga->zr36060.codec_write_memory = mgacodec_write_memory;
  1007. mga->zr36060.codec_reset = mgacodec_zr36060_reset;
  1008. mga->zr36060.codec_start = mgacodec_zr6060_start;
  1009. /*******************************************/
  1010. /* Setup addresses for the Codec Interface */
  1011. /*******************************************/
  1012. /* p. 3-68 of the MGA HandBook : the Codec Addr must be aligned
  1013.    on a 1Kb boundary */
  1014. mga->codecaddr = ((u32)mga->fb + 0x0004000) & ~0xFF;
  1015.                 /* reset the device */
  1016.                 _mgawrite( mga, VINCTL, 0x0101ab00 );
  1017.                 /* setup the i2c */
  1018.                 sprintf( mga->i2c.name, "mga%d", found );
  1019.                 mga->i2c.id = I2C_BUSID_MGA;
  1020.                 mga->i2c.data = mga;
  1021.             #if LINUX_VERSION_CODE >= 0x020100
  1022.                 mga->i2c.bus_lock = SPIN_LOCK_UNLOCKED;
  1023.             #endif
  1024.                 mga->i2c.attach_inform = _mgai2c_attach;
  1025.                 mga->i2c.detach_inform = _mgai2c_detach;
  1026.                 mga->i2c.i2c_setlines = _mgai2c_setlines;
  1027.                 mga->i2c.i2c_getdataline = _mgai2c_getdataline;
  1028.                 mga->i2c.i2c_read = NULL;
  1029.                 mga->i2c.i2c_write = NULL;
  1030.                 i2c_register_bus( &mga->i2c );
  1031.                 sprintf( mga->name, "mgavideo%d", found );
  1032.                 /* okay everything looks good */
  1033.                 dprintk( "mgavideo: Found %s: device 0x%x irq %in", mga->name, mga->device, mga->irq );
  1034.                 
  1035.                 if( ++found >= NBOARDS )
  1036.                         break;
  1037.         }
  1038.         if( !found )
  1039.                 return -ENODEV;
  1040.         return 0;
  1041. }
  1042. #ifdef MODULE
  1043. void cleanup_module( void )
  1044. {
  1045.         int i;
  1046.         struct mga_dev* mga;
  1047.         for( i=0; i<NBOARDS; i++ )
  1048.         {
  1049.                 mga = &mgavideo_dev[i];
  1050.                 if( mga->ctrl )
  1051.                 {
  1052.                         i2c_unregister_bus( &mga->i2c );
  1053.                         iounmap( (void*)mga->ctrl );
  1054.                         iounmap((void*)mga->fb);
  1055.                 }
  1056.         }
  1057. }
  1058. #endif