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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* 
  2.     planb - PlanB frame grabber driver
  3.     PlanB is used in the 7x00/8x00 series of PowerMacintosh
  4.     Computers as video input DMA controller.
  5.     Copyright (C) 1998 Michel Lanners (mlan@cpu.lu)
  6.     Based largely on the bttv driver by Ralph Metzler (rjkm@thp.uni-koeln.de)
  7.     Additional debugging and coding by Takashi Oe (toe@unlserve.unl.edu)
  8.     This program is free software; you can redistribute it and/or modify
  9.     it under the terms of the GNU General Public License as published by
  10.     the Free Software Foundation; either version 2 of the License, or
  11.     (at your option) any later version.
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20. /* $Id: planb.c,v 1.18 1999/05/02 17:36:34 mlan Exp $ */
  21. #include <linux/version.h>
  22. #include <linux/init.h>
  23. #include <linux/errno.h>
  24. #include <linux/module.h>
  25. #include <linux/kernel.h>
  26. #include <linux/major.h>
  27. #include <linux/slab.h>
  28. #include <linux/types.h>
  29. #include <linux/pci.h>
  30. #include <linux/delay.h>
  31. #include <linux/vmalloc.h>
  32. #include <linux/mm.h>
  33. #include <linux/sched.h>
  34. #include <linux/wrapper.h>
  35. #include <linux/tqueue.h>
  36. #include <linux/videodev.h>
  37. #include <asm/uaccess.h>
  38. #include <asm/io.h>
  39. #include <asm/prom.h>
  40. #include <asm/dbdma.h>
  41. #include <asm/pgtable.h>
  42. #include <asm/page.h>
  43. #include <asm/irq.h>
  44. #include <asm/semaphore.h>
  45. #include "planb.h"
  46. #include "saa7196.h"
  47. /* Would you mind for some ugly debugging? */
  48. #if 0
  49. #define DEBUG(x...) printk(KERN_DEBUG ## x) /* Debug driver */
  50. #else
  51. #define DEBUG(x...)  /* Don't debug driver */
  52. #endif
  53. #if 0
  54. #define IDEBUG(x...) printk(KERN_DEBUG ## x) /* Debug interrupt part */
  55. #else
  56. #define IDEBUG(x...)  /* Don't debug interrupt part */
  57. #endif
  58. /* Ever seen a Mac with more than 1 of these? */
  59. #define PLANB_MAX 1
  60. static int planb_num;
  61. static struct planb planbs[PLANB_MAX];
  62. static volatile struct planb_registers *planb_regs;
  63. static int def_norm = PLANB_DEF_NORM; /* default norm */
  64. static int video_nr = -1;
  65. MODULE_PARM(def_norm, "i");
  66. MODULE_PARM_DESC(def_norm, "Default startup norm (0=PAL, 1=NTSC, 2=SECAM)");
  67. MODULE_PARM(video_nr,"i");
  68. MODULE_LICENSE("GPL");
  69. /* ------------------ PlanB Exported Functions ------------------ */
  70. static long planb_write(struct video_device *, const char *, unsigned long, int);
  71. static long planb_read(struct video_device *, char *, unsigned long, int);
  72. static int planb_open(struct video_device *, int);
  73. static void planb_close(struct video_device *);
  74. static int planb_ioctl(struct video_device *, unsigned int, void *);
  75. static int planb_mmap(struct video_device *, const char *, unsigned long);
  76. static void planb_irq(int, void *, struct pt_regs *);
  77. static void release_planb(void);
  78. static int init_planbs(void);
  79. /* ------------------ PlanB Internal Functions ------------------ */
  80. static int planb_prepare_open(struct planb *);
  81. static void planb_prepare_close(struct planb *);
  82. static void saa_write_reg(unsigned char, unsigned char);
  83. static unsigned char saa_status(int, struct planb *);
  84. static void saa_set(unsigned char, unsigned char, struct planb *);
  85. static void saa_init_regs(struct planb *);
  86. static int grabbuf_alloc(struct planb *);
  87. static int vgrab(struct planb *, struct video_mmap *);
  88. static void add_clip(struct planb *, struct video_clip *);
  89. static void fill_cmd_buff(struct planb *);
  90. static void cmd_buff(struct planb *);
  91. static volatile struct dbdma_cmd *setup_grab_cmd(int, struct planb *);
  92. static void overlay_start(struct planb *);
  93. static void overlay_stop(struct planb *);
  94. static inline void tab_cmd_dbdma(volatile struct dbdma_cmd *, unsigned short,
  95. unsigned int);
  96. static inline void tab_cmd_store(volatile struct dbdma_cmd *, unsigned int,
  97. unsigned int);
  98. static inline void tab_cmd_gen(volatile struct dbdma_cmd *, unsigned short,
  99. unsigned short, unsigned int, unsigned int);
  100. static int init_planb(struct planb *);
  101. static int find_planb(void);
  102. static void planb_pre_capture(int, int, struct planb *);
  103. static volatile struct dbdma_cmd *cmd_geo_setup(volatile struct dbdma_cmd *,
  104. int, int, int, int, int, struct planb *);
  105. static inline void planb_dbdma_stop(volatile struct dbdma_regs *);
  106. static unsigned int saa_geo_setup(int, int, int, int, struct planb *);
  107. static inline int overlay_is_active(struct planb *);
  108. /*******************************/
  109. /* Memory management functions */
  110. /*******************************/
  111. static int grabbuf_alloc(struct planb *pb)
  112. {
  113. int i, npage;
  114. npage = MAX_GBUFFERS * ((PLANB_MAX_FBUF / PAGE_SIZE + 1)
  115. #ifndef PLANB_GSCANLINE
  116. + MAX_LNUM
  117. #endif /* PLANB_GSCANLINE */
  118. );
  119. if ((pb->rawbuf = (unsigned char**) kmalloc (npage
  120. * sizeof(unsigned long), GFP_KERNEL)) == 0)
  121. return -ENOMEM;
  122. for (i = 0; i < npage; i++) {
  123. pb->rawbuf[i] = (unsigned char *)__get_free_pages(GFP_KERNEL
  124. |GFP_DMA, 0);
  125. if (!pb->rawbuf[i])
  126. break;
  127. mem_map_reserve(virt_to_page(pb->rawbuf[i]));
  128. }
  129. if (i-- < npage) {
  130. printk(KERN_DEBUG "PlanB: init_grab: grab buffer not allocatedn");
  131. for (; i > 0; i--) {
  132. mem_map_unreserve(virt_to_page(pb->rawbuf[i]));
  133. free_pages((unsigned long)pb->rawbuf[i], 0);
  134. }
  135. kfree(pb->rawbuf);
  136. return -ENOBUFS;
  137. }
  138. pb->rawbuf_size = npage;
  139. return 0;
  140. }
  141. /*****************************/
  142. /* Hardware access functions */
  143. /*****************************/
  144. static void saa_write_reg(unsigned char addr, unsigned char val)
  145. {
  146. planb_regs->saa_addr = addr; eieio();
  147. planb_regs->saa_regval = val; eieio();
  148. return;
  149. }
  150. /* return  status byte 0 or 1: */
  151. static unsigned char saa_status(int byte, struct planb *pb)
  152. {
  153. saa_regs[pb->win.norm][SAA7196_STDC] =
  154. (saa_regs[pb->win.norm][SAA7196_STDC] & ~2) | ((byte & 1) << 1);
  155. saa_write_reg (SAA7196_STDC, saa_regs[pb->win.norm][SAA7196_STDC]);
  156. /* Let's wait 30msec for this one */
  157. current->state = TASK_INTERRUPTIBLE;
  158. #if LINUX_VERSION_CODE >= 0x02017F
  159. schedule_timeout(30 * HZ / 1000);
  160. #else
  161. current->timeout = jiffies + 30 * HZ / 1000; /* 30 ms */;
  162. schedule();
  163. #endif
  164. return (unsigned char)in_8 (&planb_regs->saa_status);
  165. }
  166. static void saa_set(unsigned char addr, unsigned char val, struct planb *pb)
  167. {
  168. if(saa_regs[pb->win.norm][addr] != val) {
  169. saa_regs[pb->win.norm][addr] = val;
  170. saa_write_reg (addr, val);
  171. }
  172. return;
  173. }
  174. static void saa_init_regs(struct planb *pb)
  175. {
  176. int i;
  177. for (i = 0; i < SAA7196_NUMREGS; i++)
  178. saa_write_reg (i, saa_regs[pb->win.norm][i]);
  179. }
  180. static unsigned int saa_geo_setup(int width, int height, int interlace, int bpp,
  181. struct planb *pb)
  182. {
  183. int ht, norm = pb->win.norm;
  184. switch(bpp) {
  185. case 2:
  186. /* RGB555+a 1x16-bit + 16-bit transparent */
  187. saa_regs[norm][SAA7196_FMTS] &= ~0x3;
  188. break;
  189. case 1:
  190. case 4:
  191. /* RGB888 1x24-bit + 8-bit transparent */
  192. saa_regs[norm][SAA7196_FMTS] &= ~0x1;
  193. saa_regs[norm][SAA7196_FMTS] |= 0x2;
  194. break;
  195. default:
  196. return -EINVAL;
  197. }
  198. ht = (interlace ? height / 2 : height);
  199. saa_regs[norm][SAA7196_OUTPIX] = (unsigned char) (width & 0x00ff);
  200. saa_regs[norm][SAA7196_HFILT] = (saa_regs[norm][SAA7196_HFILT] & ~0x3)
  201. | (width >> 8 & 0x3);
  202. saa_regs[norm][SAA7196_OUTLINE] = (unsigned char) (ht & 0xff);
  203. saa_regs[norm][SAA7196_VYP] = (saa_regs[norm][SAA7196_VYP] & ~0x3)
  204. | (ht >> 8 & 0x3);
  205. /* feed both fields if interlaced, or else feed only even fields */
  206. saa_regs[norm][SAA7196_FMTS] = (interlace) ?
  207. (saa_regs[norm][SAA7196_FMTS] & ~0x60)
  208. : (saa_regs[norm][SAA7196_FMTS] | 0x60);
  209. /* transparent mode; extended format enabled */
  210. saa_regs[norm][SAA7196_DPATH] |= 0x3;
  211. return 0;
  212. }
  213. /***************************/
  214. /* DBDMA support functions */
  215. /***************************/
  216. static inline void planb_dbdma_restart(volatile struct dbdma_regs *ch)
  217. {
  218. out_le32(&ch->control, PLANB_CLR(RUN));
  219. out_le32(&ch->control, PLANB_SET(RUN|WAKE) | PLANB_CLR(PAUSE));
  220. }
  221. static inline void planb_dbdma_stop(volatile struct dbdma_regs *ch)
  222. {
  223. int i = 0;
  224. out_le32(&ch->control, PLANB_CLR(RUN) | PLANB_SET(FLUSH));
  225. while((in_le32(&ch->status) == (ACTIVE | FLUSH)) && (i < 999)) {
  226. IDEBUG("PlanB: waiting for DMA to stopn");
  227. i++;
  228. }
  229. }
  230. static inline void tab_cmd_dbdma(volatile struct dbdma_cmd *ch,
  231. unsigned short command, unsigned int cmd_dep)
  232. {
  233. st_le16(&ch->command, command);
  234. st_le32(&ch->cmd_dep, cmd_dep);
  235. }
  236. static inline void tab_cmd_store(volatile struct dbdma_cmd *ch,
  237. unsigned int phy_addr, unsigned int cmd_dep)
  238. {
  239. st_le16(&ch->command, STORE_WORD | KEY_SYSTEM);
  240. st_le16(&ch->req_count, 4);
  241. st_le32(&ch->phy_addr, phy_addr);
  242. st_le32(&ch->cmd_dep, cmd_dep);
  243. }
  244. static inline void tab_cmd_gen(volatile struct dbdma_cmd *ch,
  245. unsigned short command, unsigned short req_count,
  246. unsigned int phy_addr, unsigned int cmd_dep)
  247. {
  248. st_le16(&ch->command, command);
  249. st_le16(&ch->req_count, req_count);
  250. st_le32(&ch->phy_addr, phy_addr);
  251. st_le32(&ch->cmd_dep, cmd_dep);
  252. }
  253. static volatile struct dbdma_cmd *cmd_geo_setup(
  254. volatile struct dbdma_cmd *c1, int width, int height, int interlace,
  255. int bpp, int clip, struct planb *pb)
  256. {
  257. int norm = pb->win.norm;
  258. if((saa_geo_setup(width, height, interlace, bpp, pb)) != 0)
  259. return (volatile struct dbdma_cmd *)NULL;
  260. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
  261. SAA7196_FMTS);
  262. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
  263. saa_regs[norm][SAA7196_FMTS]);
  264. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
  265. SAA7196_DPATH);
  266. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
  267. saa_regs[norm][SAA7196_DPATH]);
  268. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->even),
  269. bpp | ((clip)? PLANB_CLIPMASK: 0));
  270. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->odd),
  271. bpp | ((clip)? PLANB_CLIPMASK: 0));
  272. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
  273. SAA7196_OUTPIX);
  274. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
  275. saa_regs[norm][SAA7196_OUTPIX]);
  276. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
  277. SAA7196_HFILT);
  278. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
  279. saa_regs[norm][SAA7196_HFILT]);
  280. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
  281. SAA7196_OUTLINE);
  282. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
  283. saa_regs[norm][SAA7196_OUTLINE]);
  284. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
  285. SAA7196_VYP);
  286. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
  287. saa_regs[norm][SAA7196_VYP]);
  288. return c1;
  289. }
  290. /******************************/
  291. /* misc. supporting functions */
  292. /******************************/
  293. static inline void planb_lock(struct planb *pb)
  294. {
  295. down(&pb->lock);
  296. }
  297. static inline void planb_unlock(struct planb *pb)
  298. {
  299. up(&pb->lock);
  300. }
  301. /***************/
  302. /* Driver Core */
  303. /***************/
  304. static int planb_prepare_open(struct planb *pb)
  305. {
  306. int i, size;
  307. /* allocate memory for two plus alpha command buffers (size: max lines,
  308.    plus 40 commands handling, plus 1 alignment), plus dummy command buf,
  309.    plus clipmask buffer, plus frame grabbing status */
  310. size = (pb->tab_size*(2+MAX_GBUFFERS*TAB_FACTOR)+1+MAX_GBUFFERS
  311. * PLANB_DUMMY)*sizeof(struct dbdma_cmd)
  312. +(PLANB_MAXLINES*((PLANB_MAXPIXELS+7)& ~7))/8
  313. +MAX_GBUFFERS*sizeof(unsigned int);
  314. if ((pb->priv_space = kmalloc (size, GFP_KERNEL)) == 0)
  315. return -ENOMEM;
  316. memset ((void *) pb->priv_space, 0, size);
  317. pb->overlay_last1 = pb->ch1_cmd = (volatile struct dbdma_cmd *)
  318. DBDMA_ALIGN (pb->priv_space);
  319. pb->overlay_last2 = pb->ch2_cmd = pb->ch1_cmd + pb->tab_size;
  320. pb->ch1_cmd_phys = virt_to_bus(pb->ch1_cmd);
  321. pb->cap_cmd[0] = pb->ch2_cmd + pb->tab_size;
  322. pb->pre_cmd[0] = pb->cap_cmd[0] + pb->tab_size * TAB_FACTOR;
  323. for (i = 1; i < MAX_GBUFFERS; i++) {
  324. pb->cap_cmd[i] = pb->pre_cmd[i-1] + PLANB_DUMMY;
  325. pb->pre_cmd[i] = pb->cap_cmd[i] + pb->tab_size * TAB_FACTOR;
  326. }
  327. pb->frame_stat=(volatile unsigned int *)(pb->pre_cmd[MAX_GBUFFERS-1]
  328. + PLANB_DUMMY);
  329. pb->mask = (unsigned char *)(pb->frame_stat+MAX_GBUFFERS);
  330. pb->rawbuf = NULL;
  331. pb->rawbuf_size = 0;
  332. pb->grabbing = 0;
  333. for (i = 0; i < MAX_GBUFFERS; i++) {
  334. pb->frame_stat[i] = GBUFFER_UNUSED;
  335. pb->gwidth[i] = 0;
  336. pb->gheight[i] = 0;
  337. pb->gfmt[i] = 0;
  338. pb->gnorm_switch[i] = 0;
  339. #ifndef PLANB_GSCANLINE
  340. pb->lsize[i] = 0;
  341. pb->lnum[i] = 0;
  342. #endif /* PLANB_GSCANLINE */
  343. }
  344. pb->gcount = 0;
  345. pb->suspend = 0;
  346. pb->last_fr = -999;
  347. pb->prev_last_fr = -999;
  348. /* Reset DMA controllers */
  349. planb_dbdma_stop(&pb->planb_base->ch2);
  350. planb_dbdma_stop(&pb->planb_base->ch1);
  351. return 0;
  352. }
  353. static void planb_prepare_close(struct planb *pb)
  354. {
  355. int i;
  356. /* make sure the dma's are idle */
  357. planb_dbdma_stop(&pb->planb_base->ch2);
  358. planb_dbdma_stop(&pb->planb_base->ch1);
  359. /* free kernel memory of command buffers */
  360. if(pb->priv_space != 0) {
  361. kfree (pb->priv_space);
  362. pb->priv_space = 0;
  363. pb->cmd_buff_inited = 0;
  364. }
  365. if(pb->rawbuf) {
  366. for (i = 0; i < pb->rawbuf_size; i++) {
  367. mem_map_unreserve(virt_to_page(pb->rawbuf[i]));
  368. free_pages((unsigned long)pb->rawbuf[i], 0);
  369. }
  370. kfree(pb->rawbuf);
  371. }
  372. pb->rawbuf = NULL;
  373. }
  374. /*****************************/
  375. /* overlay support functions */
  376. /*****************************/
  377. static void overlay_start(struct planb *pb)
  378. {
  379. DEBUG("PlanB: overlay_start()n");
  380. if(ACTIVE & in_le32(&pb->planb_base->ch1.status)) {
  381. DEBUG("PlanB: presumably, grabbing is in progress...n");
  382. planb_dbdma_stop(&pb->planb_base->ch2);
  383. out_le32 (&pb->planb_base->ch2.cmdptr,
  384. virt_to_bus(pb->ch2_cmd));
  385. planb_dbdma_restart(&pb->planb_base->ch2);
  386. st_le16 (&pb->ch1_cmd->command, DBDMA_NOP);
  387. tab_cmd_dbdma(pb->last_cmd[pb->last_fr],
  388. DBDMA_NOP | BR_ALWAYS,
  389. virt_to_bus(pb->ch1_cmd));
  390. eieio();
  391. pb->prev_last_fr = pb->last_fr;
  392. pb->last_fr = -2;
  393. if(!(ACTIVE & in_le32(&pb->planb_base->ch1.status))) {
  394. IDEBUG("PlanB: became inactive "
  395. "in the mean time... reactivatingn");
  396. planb_dbdma_stop(&pb->planb_base->ch1);
  397. out_le32 (&pb->planb_base->ch1.cmdptr,
  398. virt_to_bus(pb->ch1_cmd));
  399. planb_dbdma_restart(&pb->planb_base->ch1);
  400. }
  401. } else {
  402. DEBUG("PlanB: currently idle, so can do whatevern");
  403. planb_dbdma_stop(&pb->planb_base->ch2);
  404. planb_dbdma_stop(&pb->planb_base->ch1);
  405. st_le32 (&pb->planb_base->ch2.cmdptr,
  406. virt_to_bus(pb->ch2_cmd));
  407. st_le32 (&pb->planb_base->ch1.cmdptr,
  408. virt_to_bus(pb->ch1_cmd));
  409. out_le16 (&pb->ch1_cmd->command, DBDMA_NOP);
  410. planb_dbdma_restart(&pb->planb_base->ch2);
  411. planb_dbdma_restart(&pb->planb_base->ch1);
  412. pb->last_fr = -1;
  413. }
  414. return;
  415. }
  416. static void overlay_stop(struct planb *pb)
  417. {
  418. DEBUG("PlanB: overlay_stop()n");
  419. if(pb->last_fr == -1) {
  420. DEBUG("PlanB: no grabbing, it seems...n");
  421. planb_dbdma_stop(&pb->planb_base->ch2);
  422. planb_dbdma_stop(&pb->planb_base->ch1);
  423. pb->last_fr = -999;
  424. } else if(pb->last_fr == -2) {
  425. unsigned int cmd_dep;
  426. tab_cmd_dbdma(pb->cap_cmd[pb->prev_last_fr], DBDMA_STOP, 0);
  427. eieio();
  428. cmd_dep = (unsigned int)in_le32(&pb->overlay_last1->cmd_dep);
  429. if(overlay_is_active(pb)) {
  430. DEBUG("PlanB: overlay is currently activen");
  431. planb_dbdma_stop(&pb->planb_base->ch2);
  432. planb_dbdma_stop(&pb->planb_base->ch1);
  433. if(cmd_dep != pb->ch1_cmd_phys) {
  434. out_le32(&pb->planb_base->ch1.cmdptr,
  435. virt_to_bus(pb->overlay_last1));
  436. planb_dbdma_restart(&pb->planb_base->ch1);
  437. }
  438. }
  439. pb->last_fr = pb->prev_last_fr;
  440. pb->prev_last_fr = -999;
  441. }
  442. return;
  443. }
  444. static void suspend_overlay(struct planb *pb)
  445. {
  446. int fr = -1;
  447. struct dbdma_cmd last;
  448. DEBUG("PlanB: suspend_overlay: %dn", pb->suspend);
  449. if(pb->suspend++)
  450. return;
  451. if(ACTIVE & in_le32(&pb->planb_base->ch1.status)) {
  452. if(pb->last_fr == -2) {
  453. fr = pb->prev_last_fr;
  454. memcpy(&last, (void*)pb->last_cmd[fr], sizeof(last));
  455. tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0);
  456. }
  457. if(overlay_is_active(pb)) {
  458. planb_dbdma_stop(&pb->planb_base->ch2);
  459. planb_dbdma_stop(&pb->planb_base->ch1);
  460. pb->suspended.overlay = 1;
  461. pb->suspended.frame = fr;
  462. memcpy(&pb->suspended.cmd, &last, sizeof(last));
  463. return;
  464. }
  465. }
  466. pb->suspended.overlay = 0;
  467. pb->suspended.frame = fr;
  468. memcpy(&pb->suspended.cmd, &last, sizeof(last));
  469. return;
  470. }
  471. static void resume_overlay(struct planb *pb)
  472. {
  473. DEBUG("PlanB: resume_overlay: %dn", pb->suspend);
  474. if(pb->suspend > 1)
  475. return;
  476. if(pb->suspended.frame != -1) {
  477. memcpy((void*)pb->last_cmd[pb->suspended.frame],
  478. &pb->suspended.cmd, sizeof(pb->suspended.cmd));
  479. }
  480. if(ACTIVE & in_le32(&pb->planb_base->ch1.status)) {
  481. goto finish;
  482. }
  483. if(pb->suspended.overlay) {
  484. DEBUG("PlanB: overlay being resumedn");
  485. st_le16 (&pb->ch1_cmd->command, DBDMA_NOP);
  486. st_le16 (&pb->ch2_cmd->command, DBDMA_NOP);
  487. /* Set command buffer addresses */
  488. st_le32(&pb->planb_base->ch1.cmdptr,
  489. virt_to_bus(pb->overlay_last1));
  490. out_le32(&pb->planb_base->ch2.cmdptr,
  491. virt_to_bus(pb->overlay_last2));
  492. /* Start the DMA controller */
  493. out_le32 (&pb->planb_base->ch2.control,
  494. PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE));
  495. out_le32 (&pb->planb_base->ch1.control,
  496. PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE));
  497. } else if(pb->suspended.frame != -1) {
  498. out_le32(&pb->planb_base->ch1.cmdptr,
  499. virt_to_bus(pb->last_cmd[pb->suspended.frame]));
  500. out_le32 (&pb->planb_base->ch1.control,
  501. PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE));
  502. }
  503. finish:
  504. pb->suspend--;
  505. wake_up_interruptible(&pb->suspendq);
  506. }
  507. static void add_clip(struct planb *pb, struct video_clip *clip) 
  508. {
  509. volatile unsigned char *base;
  510. int xc = clip->x, yc = clip->y;
  511. int wc = clip->width, hc = clip->height;
  512. int ww = pb->win.width, hw = pb->win.height;
  513. int x, y, xtmp1, xtmp2;
  514. DEBUG("PlanB: clip %dx%d+%d+%dn", wc, hc, xc, yc);
  515. if(xc < 0) {
  516. wc += xc;
  517. xc = 0;
  518. }
  519. if(yc < 0) {
  520. hc += yc;
  521. yc = 0;
  522. }
  523. if(xc + wc > ww)
  524. wc = ww - xc;
  525. if(wc <= 0) /* Nothing to do */
  526. return;
  527. if(yc + hc > hw)
  528. hc = hw - yc;
  529. for (y = yc; y < yc+hc; y++) {
  530. xtmp1=xc>>3;
  531. xtmp2=(xc+wc)>>3;
  532. base = pb->mask + y*96;
  533. if(xc != 0 || wc >= 8)
  534. *(base + xtmp1) &= (unsigned char)(0x00ff &
  535. (0xff00 >> (xc&7)));
  536. for (x = xtmp1 + 1; x < xtmp2; x++) {
  537. *(base + x) = 0;
  538. }
  539. if(xc < (ww & ~0x7))
  540. *(base + xtmp2) &= (unsigned char)(0x00ff >>
  541. ((xc+wc) & 7));
  542. }
  543. return;
  544. }
  545. static void fill_cmd_buff(struct planb *pb)
  546. {
  547. int restore = 0;
  548. volatile struct dbdma_cmd last;
  549. DEBUG("PlanB: fill_cmd_buff()n");
  550. if(pb->overlay_last1 != pb->ch1_cmd) {
  551. restore = 1;
  552. last = *(pb->overlay_last1);
  553. }
  554. memset ((void *) pb->ch1_cmd, 0, 2 * pb->tab_size
  555. * sizeof(struct dbdma_cmd));
  556. cmd_buff (pb);
  557. if(restore)
  558. *(pb->overlay_last1) = last;
  559. if(pb->suspended.overlay) {
  560. unsigned long jump_addr = in_le32(&pb->overlay_last1->cmd_dep);
  561. if(jump_addr != pb->ch1_cmd_phys) {
  562. int i;
  563. DEBUG("PlanB: adjusting ch1's jump addressn");
  564. for(i = 0; i < MAX_GBUFFERS; i++) {
  565. if(pb->need_pre_capture[i]) {
  566.     if(jump_addr == virt_to_bus(pb->pre_cmd[i]))
  567. goto found;
  568. } else {
  569.     if(jump_addr == virt_to_bus(pb->cap_cmd[i]))
  570. goto found;
  571. }
  572. }
  573. DEBUG("PlanB: not found...n");
  574. goto out;
  575. found:
  576. if(pb->need_pre_capture[i])
  577. out_le32(&pb->pre_cmd[i]->phy_addr,
  578. virt_to_bus(pb->overlay_last1));
  579. else
  580. out_le32(&pb->cap_cmd[i]->phy_addr,
  581. virt_to_bus(pb->overlay_last1));
  582. }
  583. }
  584. out:
  585. pb->cmd_buff_inited = 1;
  586. return;
  587. }
  588. static void cmd_buff(struct planb *pb)
  589. {
  590. int i, bpp, count, nlines, stepsize, interlace;
  591. unsigned long base, jump, addr_com, addr_dep;
  592. volatile struct dbdma_cmd *c1 = pb->ch1_cmd;
  593. volatile struct dbdma_cmd *c2 = pb->ch2_cmd;
  594. interlace = pb->win.interlace;
  595. bpp = pb->win.bpp;
  596. count = (bpp * ((pb->win.x + pb->win.width > pb->win.swidth) ?
  597. (pb->win.swidth - pb->win.x) : pb->win.width));
  598. nlines = ((pb->win.y + pb->win.height > pb->win.sheight) ?
  599. (pb->win.sheight - pb->win.y) : pb->win.height);
  600. /* Do video in: */
  601. /* Preamble commands: */
  602. addr_com = virt_to_bus(c1);
  603. addr_dep = virt_to_bus(&c1->cmd_dep);
  604. tab_cmd_dbdma(c1++, DBDMA_NOP, 0);
  605. jump = virt_to_bus(c1+16); /* 14 by cmd_geo_setup() and 2 for padding */
  606. if((c1 = cmd_geo_setup(c1, pb->win.width, pb->win.height, interlace,
  607. bpp, 1, pb)) == NULL) {
  608. printk(KERN_WARNING "PlanB: encountered serious problemsn");
  609. tab_cmd_dbdma(pb->ch1_cmd + 1, DBDMA_STOP, 0);
  610. tab_cmd_dbdma(pb->ch2_cmd + 1, DBDMA_STOP, 0);
  611. return;
  612. }
  613. tab_cmd_store(c1++, addr_com, (unsigned)(DBDMA_NOP | BR_ALWAYS) << 16);
  614. tab_cmd_store(c1++, addr_dep, jump);
  615. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel),
  616. PLANB_SET(FIELD_SYNC));
  617. /* (1) wait for field sync to be set */
  618. tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
  619. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
  620. PLANB_SET(ODD_FIELD));
  621. /* wait for field sync to be cleared */
  622. tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
  623. /* if not odd field, wait until field sync is set again */
  624. tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;
  625. /* assert ch_sync to ch2 */
  626. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch2.control),
  627. PLANB_SET(CH_SYNC));
  628. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
  629. PLANB_SET(DMA_ABORT));
  630. base = (pb->frame_buffer_phys + pb->offset + pb->win.y * (pb->win.bpl
  631. + pb->win.pad) + pb->win.x * bpp);
  632. if (interlace) {
  633. stepsize = 2;
  634. jump = virt_to_bus(c1 + (nlines + 1) / 2);
  635. } else {
  636. stepsize = 1;
  637. jump = virt_to_bus(c1 + nlines);
  638. }
  639. /* even field data: */
  640. for (i=0; i < nlines; i += stepsize, c1++)
  641. tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET,
  642. count, base + i * (pb->win.bpl + pb->win.pad), jump);
  643. /* For non-interlaced, we use even fields only */
  644. if (!interlace)
  645. goto cmd_tab_data_end;
  646. /* Resync to odd field */
  647. /* (2) wait for field sync to be set */
  648. tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
  649. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
  650. PLANB_SET(ODD_FIELD));
  651. /* wait for field sync to be cleared */
  652. tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
  653. /* if not odd field, wait until field sync is set again */
  654. tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;
  655. /* assert ch_sync to ch2 */
  656. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch2.control),
  657. PLANB_SET(CH_SYNC));
  658. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
  659. PLANB_SET(DMA_ABORT));
  660. /* odd field data: */
  661. jump = virt_to_bus(c1 + nlines / 2);
  662. for (i=1; i < nlines; i += stepsize, c1++)
  663. tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,
  664. base + i * (pb->win.bpl + pb->win.pad), jump);
  665. /* And jump back to the start */
  666. cmd_tab_data_end:
  667. pb->overlay_last1 = c1; /* keep a pointer to the last command */
  668. tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(pb->ch1_cmd));
  669. /* Clipmask command buffer */
  670. /* Preamble commands: */
  671. tab_cmd_dbdma(c2++, DBDMA_NOP, 0);
  672. tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.wait_sel),
  673. PLANB_SET(CH_SYNC));
  674. /* wait until ch1 asserts ch_sync */
  675. tab_cmd_dbdma(c2++, DBDMA_NOP | WAIT_IFCLR, 0);
  676. /* clear ch_sync asserted by ch1 */
  677. tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.control),
  678. PLANB_CLR(CH_SYNC));
  679. tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.wait_sel),
  680. PLANB_SET(FIELD_SYNC));
  681. tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.br_sel),
  682. PLANB_SET(ODD_FIELD));
  683. /* jump to end of even field if appropriate */
  684. /* this points to (interlace)? pos. C: pos. B */
  685. jump = (interlace) ? virt_to_bus(c2 + (nlines + 1) / 2 + 2):
  686. virt_to_bus(c2 + nlines + 2);
  687. /* if odd field, skip over to odd field clipmasking */
  688. tab_cmd_dbdma(c2++, DBDMA_NOP | BR_IFSET, jump);
  689. /* even field mask: */
  690. tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.br_sel),
  691. PLANB_SET(DMA_ABORT));
  692. /* this points to pos. B */
  693. jump = (interlace) ? virt_to_bus(c2 + nlines + 1):
  694. virt_to_bus(c2 + nlines);
  695. base = virt_to_bus(pb->mask);
  696. for (i=0; i < nlines; i += stepsize, c2++)
  697. tab_cmd_gen(c2, OUTPUT_MORE | KEY_STREAM0 | BR_IFSET, 96,
  698. base + i * 96, jump);
  699. /* For non-interlaced, we use only even fields */
  700. if(!interlace)
  701. goto cmd_tab_mask_end;
  702. /* odd field mask: */
  703. /* C */ tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.br_sel),
  704. PLANB_SET(DMA_ABORT));
  705. /* this points to pos. B */
  706. jump = virt_to_bus(c2 + nlines / 2);
  707. base = virt_to_bus(pb->mask);
  708. for (i=1; i < nlines; i += 2, c2++)     /* abort if set */
  709. tab_cmd_gen(c2, OUTPUT_MORE | KEY_STREAM0 | BR_IFSET, 96,
  710. base + i * 96, jump);
  711. /* Inform channel 1 and jump back to start */
  712. cmd_tab_mask_end:
  713. /* ok, I just realized this is kind of flawed. */
  714. /* this part is reached only after odd field clipmasking. */
  715. /* wanna clean up? */
  716. /* wait for field sync to be set */
  717. /* corresponds to fsync (1) of ch1 */
  718. /* B */ tab_cmd_dbdma(c2++, DBDMA_NOP | WAIT_IFCLR, 0);
  719. /* restart ch1, meant to clear any dead bit or something */
  720. tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch1.control),
  721. PLANB_CLR(RUN));
  722. tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch1.control),
  723. PLANB_SET(RUN));
  724. pb->overlay_last2 = c2; /* keep a pointer to the last command */
  725. /* start over even field clipmasking */
  726. tab_cmd_dbdma(c2, DBDMA_NOP | BR_ALWAYS, virt_to_bus(pb->ch2_cmd));
  727. eieio();
  728. return;
  729. }
  730. /*********************************/
  731. /* grabdisplay support functions */
  732. /*********************************/
  733. static int palette2fmt[] = {
  734.        0,
  735.        PLANB_GRAY,
  736.        0,
  737.        0,
  738.        0,
  739.        PLANB_COLOUR32,
  740.        PLANB_COLOUR15,
  741.        0,
  742.        0,
  743.        0,
  744.        0,
  745.        0,
  746.        0,
  747.        0,
  748.        0,
  749. };
  750. #define PLANB_PALETTE_MAX 15
  751. static inline int overlay_is_active(struct planb *pb)
  752. {
  753. unsigned int size = pb->tab_size * sizeof(struct dbdma_cmd);
  754. unsigned int caddr = (unsigned)in_le32(&pb->planb_base->ch1.cmdptr);
  755. return (in_le32(&pb->overlay_last1->cmd_dep) == pb->ch1_cmd_phys)
  756. && (caddr < (pb->ch1_cmd_phys + size))
  757. && (caddr >= (unsigned)pb->ch1_cmd_phys);
  758. }
  759. static int vgrab(struct planb *pb, struct video_mmap *mp)
  760. {
  761. unsigned int fr = mp->frame;
  762. unsigned int format;
  763. if(pb->rawbuf==NULL) {
  764. int err;
  765. if((err=grabbuf_alloc(pb)))
  766. return err;
  767. }
  768. IDEBUG("PlanB: grab %d: %dx%d(%u)n", pb->grabbing,
  769. mp->width, mp->height, fr);
  770. if(pb->grabbing >= MAX_GBUFFERS)
  771. return -ENOBUFS;
  772. if(fr > (MAX_GBUFFERS - 1) || fr < 0)
  773. return -EINVAL;
  774. if(mp->height <= 0 || mp->width <= 0)
  775. return -EINVAL;
  776. if(mp->format < 0 || mp->format >= PLANB_PALETTE_MAX)
  777. return -EINVAL;
  778. if((format = palette2fmt[mp->format]) == 0)
  779. return -EINVAL;
  780. if (mp->height * mp->width * format > PLANB_MAX_FBUF) /* format = bpp */
  781. return -EINVAL;
  782. planb_lock(pb);
  783. if(mp->width != pb->gwidth[fr] || mp->height != pb->gheight[fr] ||
  784. format != pb->gfmt[fr] || (pb->gnorm_switch[fr])) {
  785. int i;
  786. #ifndef PLANB_GSCANLINE
  787. unsigned int osize = pb->gwidth[fr] * pb->gheight[fr]
  788. * pb->gfmt[fr];
  789. unsigned int nsize = mp->width * mp->height * format;
  790. #endif
  791. IDEBUG("PlanB: gwidth = %d, gheight = %d, mp->format = %un",
  792. mp->width, mp->height, mp->format);
  793. #ifndef PLANB_GSCANLINE
  794. if(pb->gnorm_switch[fr])
  795. nsize = 0;
  796. if (nsize < osize) {
  797. for(i = pb->gbuf_idx[fr]; osize > 0; i++) {
  798. memset((void *)pb->rawbuf[i], 0, PAGE_SIZE);
  799. osize -= PAGE_SIZE;
  800. }
  801. }
  802. for(i = pb->l_fr_addr_idx[fr]; i < pb->l_fr_addr_idx[fr]
  803. + pb->lnum[fr]; i++)
  804. memset((void *)pb->rawbuf[i], 0, PAGE_SIZE);
  805. #else
  806. /* XXX TODO */
  807. /*
  808. if(pb->gnorm_switch[fr])
  809. memset((void *)pb->gbuffer[fr], 0,
  810. pb->gbytes_per_line * pb->gheight[fr]);
  811. else {
  812. if(mp->
  813. for(i = 0; i < pb->gheight[fr]; i++) {
  814. memset((void *)(pb->gbuffer[fr]
  815. + pb->gbytes_per_line * i
  816. }
  817. }
  818. */
  819. #endif
  820. pb->gwidth[fr] = mp->width;
  821. pb->gheight[fr] = mp->height;
  822. pb->gfmt[fr] = format;
  823. pb->last_cmd[fr] = setup_grab_cmd(fr, pb);
  824. planb_pre_capture(fr, pb->gfmt[fr], pb); /* gfmt = bpp */
  825. pb->need_pre_capture[fr] = 1;
  826. pb->gnorm_switch[fr] = 0;
  827. } else
  828. pb->need_pre_capture[fr] = 0;
  829. pb->frame_stat[fr] = GBUFFER_GRABBING;
  830. if(!(ACTIVE & in_le32(&pb->planb_base->ch1.status))) {
  831. IDEBUG("PlanB: ch1 inactive, initiating grabbingn");
  832. planb_dbdma_stop(&pb->planb_base->ch1);
  833. if(pb->need_pre_capture[fr]) {
  834. IDEBUG("PlanB: padding pre-capture sequencen");
  835. out_le32 (&pb->planb_base->ch1.cmdptr,
  836. virt_to_bus(pb->pre_cmd[fr]));
  837. } else {
  838. tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0);
  839. tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0);
  840. /* let's be on the safe side. here is not timing critical. */
  841. tab_cmd_dbdma((pb->cap_cmd[fr] + 1), DBDMA_NOP, 0);
  842. out_le32 (&pb->planb_base->ch1.cmdptr,
  843. virt_to_bus(pb->cap_cmd[fr]));
  844. }
  845. planb_dbdma_restart(&pb->planb_base->ch1);
  846. pb->last_fr = fr;
  847. } else {
  848. int i;
  849. IDEBUG("PlanB: ch1 active, grabbing being queuedn");
  850. if((pb->last_fr == -1) || ((pb->last_fr == -2) &&
  851. overlay_is_active(pb))) {
  852. IDEBUG("PlanB: overlay is active, grabbing deferedn");
  853. tab_cmd_dbdma(pb->last_cmd[fr],
  854. DBDMA_NOP | BR_ALWAYS,
  855. virt_to_bus(pb->ch1_cmd));
  856. if(pb->need_pre_capture[fr]) {
  857. IDEBUG("PlanB: padding pre-capture sequencen");
  858. tab_cmd_store(pb->pre_cmd[fr],
  859.     virt_to_bus(&pb->overlay_last1->cmd_dep),
  860. virt_to_bus(pb->ch1_cmd));
  861. eieio();
  862. out_le32 (&pb->overlay_last1->cmd_dep,
  863. virt_to_bus(pb->pre_cmd[fr]));
  864. } else {
  865. tab_cmd_store(pb->cap_cmd[fr],
  866.     virt_to_bus(&pb->overlay_last1->cmd_dep),
  867. virt_to_bus(pb->ch1_cmd));
  868. tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
  869. DBDMA_NOP, 0);
  870. eieio();
  871. out_le32 (&pb->overlay_last1->cmd_dep,
  872. virt_to_bus(pb->cap_cmd[fr]));
  873. }
  874. for(i = 0; overlay_is_active(pb) && i < 999; i++)
  875. IDEBUG("PlanB: waiting for overlay donen");
  876. tab_cmd_dbdma(pb->ch1_cmd, DBDMA_NOP, 0);
  877. pb->prev_last_fr = fr;
  878. pb->last_fr = -2;
  879. } else if(pb->last_fr == -2) {
  880. IDEBUG("PlanB: mixed mode detected, grabbing"
  881. " will be done before activating overlayn");
  882. tab_cmd_dbdma(pb->ch1_cmd, DBDMA_NOP, 0);
  883. if(pb->need_pre_capture[fr]) {
  884. IDEBUG("PlanB: padding pre-capture sequencen");
  885. tab_cmd_dbdma(pb->last_cmd[pb->prev_last_fr],
  886. DBDMA_NOP | BR_ALWAYS,
  887. virt_to_bus(pb->pre_cmd[fr]));
  888. eieio();
  889. } else {
  890. tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0);
  891. if(pb->gwidth[pb->prev_last_fr] !=
  892. pb->gwidth[fr]
  893. || pb->gheight[pb->prev_last_fr] !=
  894. pb->gheight[fr]
  895. || pb->gfmt[pb->prev_last_fr] !=
  896. pb->gfmt[fr])
  897. tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
  898. DBDMA_NOP, 0);
  899. else
  900. tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
  901.     DBDMA_NOP | BR_ALWAYS,
  902.     virt_to_bus(pb->cap_cmd[fr] + 16));
  903. tab_cmd_dbdma(pb->last_cmd[pb->prev_last_fr],
  904. DBDMA_NOP | BR_ALWAYS,
  905. virt_to_bus(pb->cap_cmd[fr]));
  906. eieio();
  907. }
  908. tab_cmd_dbdma(pb->last_cmd[fr],
  909. DBDMA_NOP | BR_ALWAYS,
  910. virt_to_bus(pb->ch1_cmd));
  911. eieio();
  912. pb->prev_last_fr = fr;
  913. pb->last_fr = -2;
  914. } else {
  915. IDEBUG("PlanB: active grabbing session detectedn");
  916. if(pb->need_pre_capture[fr]) {
  917. IDEBUG("PlanB: padding pre-capture sequencen");
  918. tab_cmd_dbdma(pb->last_cmd[pb->last_fr],
  919. DBDMA_NOP | BR_ALWAYS,
  920. virt_to_bus(pb->pre_cmd[fr]));
  921. eieio();
  922. } else {
  923. tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0);
  924. tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0);
  925. if(pb->gwidth[pb->last_fr] != pb->gwidth[fr]
  926. || pb->gheight[pb->last_fr] !=
  927. pb->gheight[fr]
  928. || pb->gfmt[pb->last_fr] !=
  929. pb->gfmt[fr])
  930. tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
  931. DBDMA_NOP, 0);
  932. else
  933. tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
  934.     DBDMA_NOP | BR_ALWAYS,
  935.     virt_to_bus(pb->cap_cmd[fr] + 16));
  936. tab_cmd_dbdma(pb->last_cmd[pb->last_fr],
  937. DBDMA_NOP | BR_ALWAYS,
  938. virt_to_bus(pb->cap_cmd[fr]));
  939. eieio();
  940. }
  941. pb->last_fr = fr;
  942. }
  943. if(!(ACTIVE & in_le32(&pb->planb_base->ch1.status))) {
  944. IDEBUG("PlanB: became inactive in the mean time..."
  945. "reactivatingn");
  946. planb_dbdma_stop(&pb->planb_base->ch1);
  947. out_le32 (&pb->planb_base->ch1.cmdptr,
  948. virt_to_bus(pb->cap_cmd[fr]));
  949. planb_dbdma_restart(&pb->planb_base->ch1);
  950. }
  951. }
  952. pb->grabbing++;
  953. planb_unlock(pb);
  954. return 0;
  955. }
  956. static void planb_pre_capture(int fr, int bpp, struct planb *pb)
  957. {
  958. volatile struct dbdma_cmd *c1 = pb->pre_cmd[fr];
  959. int interlace = (pb->gheight[fr] > pb->maxlines/2)? 1: 0;
  960. tab_cmd_dbdma(c1++, DBDMA_NOP, 0);
  961. if((c1 = cmd_geo_setup(c1, pb->gwidth[fr], pb->gheight[fr], interlace,
  962. bpp, 0, pb)) == NULL) {
  963. printk(KERN_WARNING "PlanB: encountered some problemsn");
  964. tab_cmd_dbdma(pb->pre_cmd[fr] + 1, DBDMA_STOP, 0);
  965. return;
  966. }
  967. /* Sync to even field */
  968. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel),
  969. PLANB_SET(FIELD_SYNC));
  970. tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
  971. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
  972. PLANB_SET(ODD_FIELD));
  973. tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
  974. tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;
  975. tab_cmd_dbdma(c1++, DBDMA_NOP | INTR_ALWAYS, 0);
  976. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
  977. PLANB_SET(DMA_ABORT));
  978. /* For non-interlaced, we use even fields only */
  979. if (pb->gheight[fr] <= pb->maxlines/2)
  980. goto cmd_tab_data_end;
  981. /* Sync to odd field */
  982. tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
  983. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
  984. PLANB_SET(ODD_FIELD));
  985. tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
  986. tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;
  987. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
  988. PLANB_SET(DMA_ABORT));
  989. cmd_tab_data_end:
  990. tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(pb->cap_cmd[fr]));
  991. eieio();
  992. }
  993. static volatile struct dbdma_cmd *setup_grab_cmd(int fr, struct planb *pb)
  994. {
  995. int i, bpp, count, nlines, stepsize, interlace;
  996. #ifdef PLANB_GSCANLINE
  997. int scanline;
  998. #else
  999. int nlpp, leftover1;
  1000. unsigned long base;
  1001. #endif
  1002. unsigned long jump;
  1003. int pagei;
  1004. volatile struct dbdma_cmd *c1;
  1005. volatile struct dbdma_cmd *jump_addr;
  1006. c1 = pb->cap_cmd[fr];
  1007. interlace = (pb->gheight[fr] > pb->maxlines/2)? 1: 0;
  1008. bpp = pb->gfmt[fr]; /* gfmt = bpp */
  1009. count = bpp * pb->gwidth[fr];
  1010. nlines = pb->gheight[fr];
  1011. #ifdef PLANB_GSCANLINE
  1012. scanline = pb->gbytes_per_line;
  1013. #else
  1014. pb->lsize[fr] = count;
  1015. pb->lnum[fr] = 0;
  1016. #endif
  1017. /* Do video in: */
  1018. /* Preamble commands: */
  1019. tab_cmd_dbdma(c1++, DBDMA_NOP, 0);
  1020. tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(c1 + 16)); c1++;
  1021. if((c1 = cmd_geo_setup(c1, pb->gwidth[fr], pb->gheight[fr], interlace,
  1022. bpp, 0, pb)) == NULL) {
  1023. printk(KERN_WARNING "PlanB: encountered serious problemsn");
  1024. tab_cmd_dbdma(pb->cap_cmd[fr] + 1, DBDMA_STOP, 0);
  1025. return (pb->cap_cmd[fr] + 2);
  1026. }
  1027. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel),
  1028. PLANB_SET(FIELD_SYNC));
  1029. tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
  1030. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
  1031. PLANB_SET(ODD_FIELD));
  1032. tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
  1033. tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;
  1034. tab_cmd_dbdma(c1++, DBDMA_NOP | INTR_ALWAYS, 0);
  1035. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
  1036. PLANB_SET(DMA_ABORT));
  1037. if (interlace) {
  1038. stepsize = 2;
  1039. jump_addr = c1 + TAB_FACTOR * (nlines + 1) / 2;
  1040. } else {
  1041. stepsize = 1;
  1042. jump_addr = c1 + TAB_FACTOR * nlines;
  1043. }
  1044. jump = virt_to_bus(jump_addr);
  1045. /* even field data: */
  1046. pagei = pb->gbuf_idx[fr];
  1047. #ifdef PLANB_GSCANLINE
  1048. for (i = 0; i < nlines; i += stepsize) {
  1049. tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,
  1050. virt_to_bus(pb->rawbuf[pagei
  1051. + i * scanline / PAGE_SIZE]), jump);
  1052. }
  1053. #else
  1054. i = 0;
  1055. leftover1 = 0;
  1056. do {
  1057.     int j;
  1058.     base = virt_to_bus(pb->rawbuf[pagei]);
  1059.     nlpp = (PAGE_SIZE - leftover1) / count / stepsize;
  1060.     for(j = 0; j < nlpp && i < nlines; j++, i += stepsize, c1++)
  1061. tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET,
  1062.   count, base + count * j * stepsize + leftover1, jump);
  1063.     if(i < nlines) {
  1064. int lov0 = PAGE_SIZE - count * nlpp * stepsize - leftover1;
  1065. if(lov0 == 0)
  1066.     leftover1 = 0;
  1067. else {
  1068.     if(lov0 >= count) {
  1069. tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count, base
  1070. + count * nlpp * stepsize + leftover1, jump);
  1071.     } else {
  1072. pb->l_to_addr[fr][pb->lnum[fr]] = pb->rawbuf[pagei]
  1073. + count * nlpp * stepsize + leftover1;
  1074. pb->l_to_next_idx[fr][pb->lnum[fr]] = pagei + 1;
  1075. pb->l_to_next_size[fr][pb->lnum[fr]] = count - lov0;
  1076. tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,
  1077. virt_to_bus(pb->rawbuf[pb->l_fr_addr_idx[fr]
  1078. + pb->lnum[fr]]), jump);
  1079. if(++pb->lnum[fr] > MAX_LNUM)
  1080. pb->lnum[fr]--;
  1081.     }
  1082.     leftover1 = count * stepsize - lov0;
  1083.     i += stepsize;
  1084. }
  1085.     }
  1086.     pagei++;
  1087. } while(i < nlines);
  1088. tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, jump);
  1089. c1 = jump_addr;
  1090. #endif /* PLANB_GSCANLINE */
  1091. /* For non-interlaced, we use even fields only */
  1092. if (!interlace)
  1093. goto cmd_tab_data_end;
  1094. /* Sync to odd field */
  1095. tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
  1096. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
  1097. PLANB_SET(ODD_FIELD));
  1098. tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
  1099. tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;
  1100. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
  1101. PLANB_SET(DMA_ABORT));
  1102. /* odd field data: */
  1103. jump_addr = c1 + TAB_FACTOR * nlines / 2;
  1104. jump = virt_to_bus(jump_addr);
  1105. #ifdef PLANB_GSCANLINE
  1106. for (i = 1; i < nlines; i += stepsize) {
  1107. tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,
  1108. virt_to_bus(pb->rawbuf[pagei
  1109. + i * scanline / PAGE_SIZE]), jump);
  1110. }
  1111. #else
  1112. i = 1;
  1113. leftover1 = 0;
  1114. pagei = pb->gbuf_idx[fr];
  1115. if(nlines <= 1)
  1116.     goto skip;
  1117. do {
  1118.     int j;
  1119.     base = virt_to_bus(pb->rawbuf[pagei]);
  1120.     nlpp = (PAGE_SIZE - leftover1) / count / stepsize;
  1121.     if(leftover1 >= count) {
  1122. tab_cmd_gen(c1++, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,
  1123. base + leftover1 - count, jump);
  1124. i += stepsize;
  1125.     }
  1126.     for(j = 0; j < nlpp && i < nlines; j++, i += stepsize, c1++)
  1127. tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,
  1128. base + count * (j * stepsize + 1) + leftover1, jump);
  1129.     if(i < nlines) {
  1130. int lov0 = PAGE_SIZE - count * nlpp * stepsize - leftover1;
  1131. if(lov0 == 0)
  1132.     leftover1 = 0;
  1133. else {
  1134.     if(lov0 > count) {
  1135. pb->l_to_addr[fr][pb->lnum[fr]] = pb->rawbuf[pagei]
  1136. + count * (nlpp * stepsize + 1) + leftover1;
  1137. pb->l_to_next_idx[fr][pb->lnum[fr]] = pagei + 1;
  1138. pb->l_to_next_size[fr][pb->lnum[fr]] = count * stepsize
  1139. - lov0;
  1140. tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,
  1141. virt_to_bus(pb->rawbuf[pb->l_fr_addr_idx[fr]
  1142. + pb->lnum[fr]]), jump);
  1143. if(++pb->lnum[fr] > MAX_LNUM)
  1144. pb->lnum[fr]--;
  1145. i += stepsize;
  1146.     }
  1147.     leftover1 = count * stepsize - lov0;
  1148. }
  1149.     }
  1150.     pagei++;
  1151. } while(i < nlines);
  1152. skip:
  1153. tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, jump);
  1154. c1 = jump_addr;
  1155. #endif /* PLANB_GSCANLINE */
  1156. cmd_tab_data_end:
  1157. tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->intr_stat),
  1158. (fr << 9) | PLANB_FRM_IRQ | PLANB_GEN_IRQ);
  1159. /* stop it */
  1160. tab_cmd_dbdma(c1, DBDMA_STOP, 0);
  1161. eieio();
  1162. return c1;
  1163. }
  1164. static void planb_irq(int irq, void *dev_id, struct pt_regs * regs)
  1165. {
  1166. unsigned int stat, astat;
  1167. struct planb *pb = (struct planb *)dev_id;
  1168. IDEBUG("PlanB: planb_irq()n");
  1169. /* get/clear interrupt status bits */
  1170. eieio();
  1171. stat = in_le32(&pb->planb_base->intr_stat);
  1172. astat = stat & pb->intr_mask;
  1173. out_le32(&pb->planb_base->intr_stat, PLANB_FRM_IRQ
  1174. & ~astat & stat & ~PLANB_GEN_IRQ);
  1175. IDEBUG("PlanB: stat = %X, astat = %Xn", stat, astat);
  1176. if(astat & PLANB_FRM_IRQ) {
  1177. unsigned int fr = stat >> 9;
  1178. #ifndef PLANB_GSCANLINE
  1179. int i;
  1180. #endif
  1181. IDEBUG("PlanB: PLANB_FRM_IRQn");
  1182. pb->gcount++;
  1183. IDEBUG("PlanB: grab %d: fr = %d, gcount = %dn",
  1184. pb->grabbing, fr, pb->gcount);
  1185. #ifndef PLANB_GSCANLINE
  1186. IDEBUG("PlanB: %d * %d bytes are being copied overn",
  1187. pb->lnum[fr], pb->lsize[fr]);
  1188. for(i = 0; i < pb->lnum[fr]; i++) {
  1189. int first = pb->lsize[fr] - pb->l_to_next_size[fr][i];
  1190. memcpy(pb->l_to_addr[fr][i],
  1191. pb->rawbuf[pb->l_fr_addr_idx[fr] + i],
  1192. first);
  1193. memcpy(pb->rawbuf[pb->l_to_next_idx[fr][i]],
  1194. pb->rawbuf[pb->l_fr_addr_idx[fr] + i] + first,
  1195. pb->l_to_next_size[fr][i]);
  1196. }
  1197. #endif
  1198. pb->frame_stat[fr] = GBUFFER_DONE;
  1199. pb->grabbing--;
  1200. wake_up_interruptible(&pb->capq);
  1201. return;
  1202. }
  1203. /* incorrect interrupts? */
  1204. pb->intr_mask = PLANB_CLR_IRQ;
  1205. out_le32(&pb->planb_base->intr_stat, PLANB_CLR_IRQ);
  1206. printk(KERN_ERR "PlanB: IRQ lockup, cleared intrrupts"
  1207. " unconditionallyn");
  1208. }
  1209. /*******************************
  1210.  * Device Operations functions *
  1211.  *******************************/
  1212. static int planb_open(struct video_device *dev, int mode)
  1213. {
  1214. struct planb *pb = (struct planb *)dev;
  1215. if (pb->user == 0) {
  1216. int err;
  1217. if((err = planb_prepare_open(pb)) != 0)
  1218. return err;
  1219. }
  1220. pb->user++;
  1221. DEBUG("PlanB: device openedn");
  1222. MOD_INC_USE_COUNT;
  1223. return 0;   
  1224. }
  1225. static void planb_close(struct video_device *dev)
  1226. {
  1227. struct planb *pb = (struct planb *)dev;
  1228. if(pb->user < 1) /* ??? */
  1229. return;
  1230. planb_lock(pb);
  1231. if (pb->user == 1) {
  1232. if (pb->overlay) {
  1233. planb_dbdma_stop(&pb->planb_base->ch2);
  1234. planb_dbdma_stop(&pb->planb_base->ch1);
  1235. pb->overlay = 0;
  1236. }
  1237. planb_prepare_close(pb);
  1238. }
  1239. pb->user--;
  1240. planb_unlock(pb);
  1241. DEBUG("PlanB: device closedn");
  1242. MOD_DEC_USE_COUNT;  
  1243. }
  1244. static long planb_read(struct video_device *v, char *buf, unsigned long count,
  1245. int nonblock)
  1246. {
  1247. DEBUG("planb: read requestn");
  1248. return -EINVAL;
  1249. }
  1250. static long planb_write(struct video_device *v, const char *buf,
  1251. unsigned long count, int nonblock)
  1252. {
  1253. DEBUG("planb: write requestn");
  1254. return -EINVAL;
  1255. }
  1256. static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
  1257. {
  1258. struct planb *pb=(struct planb *)dev;
  1259.   
  1260. switch (cmd)
  1261. {
  1262. case VIDIOCGCAP:
  1263. {
  1264. struct video_capability b;
  1265. DEBUG("PlanB: IOCTL VIDIOCGCAPn");
  1266. strcpy (b.name, pb->video_dev.name);
  1267. b.type = VID_TYPE_OVERLAY | VID_TYPE_CLIPPING |
  1268.  VID_TYPE_FRAMERAM | VID_TYPE_SCALES |
  1269.  VID_TYPE_CAPTURE;
  1270. b.channels = 2; /* composite & svhs */
  1271. b.audios = 0;
  1272. b.maxwidth = PLANB_MAXPIXELS;
  1273.                         b.maxheight = PLANB_MAXLINES;
  1274.                         b.minwidth = 32; /* wild guess */
  1275.                         b.minheight = 32;
  1276.                         if (copy_to_user(arg,&b,sizeof(b)))
  1277.                                 return -EFAULT;
  1278. return 0;
  1279. }
  1280. case VIDIOCSFBUF:
  1281. {
  1282.                         struct video_buffer v;
  1283. unsigned short bpp;
  1284. unsigned int fmt;
  1285. DEBUG("PlanB: IOCTL VIDIOCSFBUFn");
  1286.                         if (!capable(CAP_SYS_ADMIN)
  1287. || !capable(CAP_SYS_RAWIO))
  1288.                                 return -EPERM;
  1289.                         if (copy_from_user(&v, arg,sizeof(v)))
  1290.                                 return -EFAULT;
  1291. planb_lock(pb);
  1292. switch(v.depth) {
  1293. case 8:
  1294. bpp = 1;
  1295. fmt = PLANB_GRAY;
  1296. break;
  1297. case 15:
  1298. case 16:
  1299. bpp = 2;
  1300. fmt = PLANB_COLOUR15;
  1301. break;
  1302. case 24:
  1303. case 32:
  1304. bpp = 4;
  1305. fmt = PLANB_COLOUR32;
  1306. break;
  1307. default:
  1308. planb_unlock(pb);
  1309.                                 return -EINVAL;
  1310. }
  1311. if (bpp * v.width > v.bytesperline) {
  1312. planb_unlock(pb);
  1313. return -EINVAL;
  1314. }
  1315. pb->win.bpp = bpp;
  1316. pb->win.color_fmt = fmt;
  1317. pb->frame_buffer_phys = (unsigned long) v.base;
  1318. pb->win.sheight = v.height;
  1319. pb->win.swidth = v.width;
  1320. pb->picture.depth = pb->win.depth = v.depth;
  1321. pb->win.bpl = pb->win.bpp * pb->win.swidth;
  1322. pb->win.pad = v.bytesperline - pb->win.bpl;
  1323.                         DEBUG("PlanB: Display at %p is %d by %d, bytedepth %d,"
  1324. " bpl %d (+ %d)n", v.base, v.width,v.height,
  1325. pb->win.bpp, pb->win.bpl, pb->win.pad);
  1326. pb->cmd_buff_inited = 0;
  1327. if(pb->overlay) {
  1328. suspend_overlay(pb);
  1329. fill_cmd_buff(pb);
  1330. resume_overlay(pb);
  1331. }
  1332. planb_unlock(pb);
  1333. return 0;
  1334. }
  1335. case VIDIOCGFBUF:
  1336. {
  1337.                         struct video_buffer v;
  1338. DEBUG("PlanB: IOCTL VIDIOCGFBUFn");
  1339. v.base = (void *)pb->frame_buffer_phys;
  1340. v.height = pb->win.sheight;
  1341. v.width = pb->win.swidth;
  1342. v.depth = pb->win.depth;
  1343. v.bytesperline = pb->win.bpl + pb->win.pad;
  1344. if (copy_to_user(arg, &v, sizeof(v)))
  1345.                                 return -EFAULT;
  1346. return 0;
  1347. }
  1348. case VIDIOCCAPTURE:
  1349. {
  1350. int i;
  1351.                         if(copy_from_user(&i, arg, sizeof(i)))
  1352.                                 return -EFAULT;
  1353. if(i==0) {
  1354. DEBUG("PlanB: IOCTL VIDIOCCAPTURE Stopn");
  1355. if (!(pb->overlay))
  1356. return 0;
  1357. planb_lock(pb);
  1358. pb->overlay = 0;
  1359. overlay_stop(pb);
  1360. planb_unlock(pb);
  1361. } else {
  1362. DEBUG("PlanB: IOCTL VIDIOCCAPTURE Startn");
  1363. if (pb->frame_buffer_phys == 0 ||
  1364.   pb->win.width == 0 ||
  1365.   pb->win.height == 0)
  1366. return -EINVAL;
  1367. if (pb->overlay)
  1368. return 0;
  1369. planb_lock(pb);
  1370. pb->overlay = 1;
  1371. if(!(pb->cmd_buff_inited))
  1372. fill_cmd_buff(pb);
  1373. overlay_start(pb);
  1374. planb_unlock(pb);
  1375. }
  1376. return 0;
  1377. }
  1378. case VIDIOCGCHAN:
  1379. {
  1380. struct video_channel v;
  1381. DEBUG("PlanB: IOCTL VIDIOCGCHANn");
  1382. if(copy_from_user(&v, arg,sizeof(v)))
  1383. return -EFAULT;
  1384. v.flags = 0;
  1385. v.tuners = 0;
  1386. v.type = VIDEO_TYPE_CAMERA;
  1387. v.norm = pb->win.norm;
  1388. switch(v.channel)
  1389. {
  1390. case 0:
  1391. strcpy(v.name,"Composite");
  1392. break;
  1393. case 1:
  1394. strcpy(v.name,"SVHS");
  1395. break;
  1396. default:
  1397. return -EINVAL;
  1398. break;
  1399. }
  1400. if(copy_to_user(arg,&v,sizeof(v)))
  1401. return -EFAULT;
  1402. return 0;
  1403. }
  1404. case VIDIOCSCHAN:
  1405. {
  1406. struct video_channel v;
  1407. DEBUG("PlanB: IOCTL VIDIOCSCHANn");
  1408. if(copy_from_user(&v, arg, sizeof(v)))
  1409. return -EFAULT;
  1410. if (v.norm != pb->win.norm) {
  1411. int i, maxlines;
  1412. switch (v.norm)
  1413. {
  1414. case VIDEO_MODE_PAL:
  1415. case VIDEO_MODE_SECAM:
  1416. maxlines = PLANB_MAXLINES;
  1417. break;
  1418. case VIDEO_MODE_NTSC:
  1419. maxlines = PLANB_NTSC_MAXLINES;
  1420. break;
  1421. default:
  1422. return -EINVAL;
  1423. break;
  1424. }
  1425. planb_lock(pb);
  1426. /* empty the grabbing queue */
  1427. while(pb->grabbing)
  1428. interruptible_sleep_on(&pb->capq);
  1429. pb->maxlines = maxlines;
  1430. pb->win.norm = v.norm;
  1431. /* Stop overlay if running */
  1432. suspend_overlay(pb);
  1433. for(i = 0; i < MAX_GBUFFERS; i++)
  1434. pb->gnorm_switch[i] = 1;
  1435. /* I know it's an overkill, but.... */
  1436. fill_cmd_buff(pb);
  1437. /* ok, now init it accordingly */
  1438. saa_init_regs (pb);
  1439. /* restart overlay if it was running */
  1440. resume_overlay(pb);
  1441. planb_unlock(pb);
  1442. }
  1443. switch(v.channel)
  1444. {
  1445. case 0: /* Composite */
  1446. saa_set (SAA7196_IOCC,
  1447. ((saa_regs[pb->win.norm][SAA7196_IOCC] &
  1448.   ~7) | 3), pb);
  1449. break;
  1450. case 1: /* SVHS */
  1451. saa_set (SAA7196_IOCC,
  1452. ((saa_regs[pb->win.norm][SAA7196_IOCC] &
  1453.   ~7) | 4), pb);
  1454. break;
  1455. default:
  1456. return -EINVAL;
  1457. break;
  1458. }
  1459. return 0;
  1460. }
  1461. case VIDIOCGPICT:
  1462. {
  1463. struct video_picture vp = pb->picture;
  1464. DEBUG("PlanB: IOCTL VIDIOCGPICTn");
  1465. switch(pb->win.color_fmt) {
  1466. case PLANB_GRAY:
  1467. vp.palette = VIDEO_PALETTE_GREY;
  1468. case PLANB_COLOUR15:
  1469. vp.palette = VIDEO_PALETTE_RGB555;
  1470. break;
  1471. case PLANB_COLOUR32:
  1472. vp.palette = VIDEO_PALETTE_RGB32;
  1473. break;
  1474. default:
  1475. vp.palette = 0;
  1476. break;
  1477. }
  1478. if(copy_to_user(arg,&vp,sizeof(vp)))
  1479. return -EFAULT;
  1480. return 0;
  1481. }
  1482. case VIDIOCSPICT:
  1483. {
  1484. struct video_picture vp;
  1485. DEBUG("PlanB: IOCTL VIDIOCSPICTn");
  1486. if(copy_from_user(&vp,arg,sizeof(vp)))
  1487. return -EFAULT;
  1488. pb->picture = vp;
  1489. /* Should we do sanity checks here? */
  1490. saa_set (SAA7196_BRIG, (unsigned char)
  1491.     ((pb->picture.brightness) >> 8), pb);
  1492. saa_set (SAA7196_HUEC, (unsigned char)
  1493.     ((pb->picture.hue) >> 8) ^ 0x80, pb);
  1494. saa_set (SAA7196_CSAT, (unsigned char)
  1495.     ((pb->picture.colour) >> 9), pb);
  1496. saa_set (SAA7196_CONT, (unsigned char)
  1497.     ((pb->picture.contrast) >> 9), pb);
  1498. return 0;
  1499. }
  1500. case VIDIOCSWIN:
  1501. {
  1502. struct video_window vw;
  1503. struct video_clip clip;
  1504. int  i;
  1505. DEBUG("PlanB: IOCTL VIDIOCSWINn");
  1506. if(copy_from_user(&vw,arg,sizeof(vw)))
  1507. return -EFAULT;
  1508. planb_lock(pb);
  1509. /* Stop overlay if running */
  1510. suspend_overlay(pb);
  1511. pb->win.interlace = (vw.height > pb->maxlines/2)? 1: 0;
  1512. if (pb->win.x != vw.x ||
  1513.     pb->win.y != vw.y ||
  1514.     pb->win.width != vw.width ||
  1515.     pb->win.height != vw.height ||
  1516.     !pb->cmd_buff_inited) {
  1517. pb->win.x = vw.x;
  1518. pb->win.y = vw.y;
  1519. pb->win.width = vw.width;
  1520. pb->win.height = vw.height;
  1521. fill_cmd_buff(pb);
  1522. }
  1523. /* Reset clip mask */
  1524. memset ((void *) pb->mask, 0xff, (pb->maxlines
  1525. * ((PLANB_MAXPIXELS + 7) & ~7)) / 8);
  1526. /* Add any clip rects */
  1527. for (i = 0; i < vw.clipcount; i++) {
  1528. if (copy_from_user(&clip, vw.clips + i,
  1529. sizeof(struct video_clip)))
  1530. return -EFAULT;
  1531. add_clip(pb, &clip);
  1532. }
  1533. /* restart overlay if it was running */
  1534. resume_overlay(pb);
  1535. planb_unlock(pb);
  1536. return 0;
  1537. }
  1538. case VIDIOCGWIN:
  1539. {
  1540. struct video_window vw;
  1541. DEBUG("PlanB: IOCTL VIDIOCGWINn");
  1542. vw.x=pb->win.x;
  1543. vw.y=pb->win.y;
  1544. vw.width=pb->win.width;
  1545. vw.height=pb->win.height;
  1546. vw.chromakey=0;
  1547. vw.flags=0;
  1548. if(pb->win.interlace)
  1549. vw.flags|=VIDEO_WINDOW_INTERLACE;
  1550. if(copy_to_user(arg,&vw,sizeof(vw)))
  1551. return -EFAULT;
  1552. return 0;
  1553. }
  1554.         case VIDIOCSYNC: {
  1555. int i;
  1556. IDEBUG("PlanB: IOCTL VIDIOCSYNCn");
  1557. if(copy_from_user((void *)&i,arg,sizeof(int)))
  1558. return -EFAULT;
  1559. IDEBUG("PlanB: sync to frame %dn", i);
  1560.                         if(i > (MAX_GBUFFERS - 1) || i < 0)
  1561.                                 return -EINVAL;
  1562. chk_grab:
  1563.                         switch (pb->frame_stat[i]) {
  1564.                         case GBUFFER_UNUSED:
  1565.                                 return -EINVAL;
  1566. case GBUFFER_GRABBING:
  1567. IDEBUG("PlanB: waiting for grab"
  1568. " done (%d)n", i);
  1569.           interruptible_sleep_on(&pb->capq);
  1570. if(signal_pending(current))
  1571. return -EINTR;
  1572. goto chk_grab;
  1573.                         case GBUFFER_DONE:
  1574.                                 pb->frame_stat[i] = GBUFFER_UNUSED;
  1575.                                 break;
  1576.                         }
  1577.                         return 0;
  1578. }
  1579.         case VIDIOCMCAPTURE:
  1580. {
  1581.                         struct video_mmap vm;
  1582. volatile unsigned int status;
  1583. IDEBUG("PlanB: IOCTL VIDIOCMCAPTUREn");
  1584. if(copy_from_user((void *) &vm,(void *)arg,sizeof(vm)))
  1585. return -EFAULT;
  1586.                         status = pb->frame_stat[vm.frame];
  1587.                         if (status != GBUFFER_UNUSED)
  1588.                                 return -EBUSY;
  1589.         return vgrab(pb, &vm);
  1590. }
  1591. case VIDIOCGMBUF:
  1592. {
  1593. int i;
  1594. struct video_mbuf vm;
  1595. DEBUG("PlanB: IOCTL VIDIOCGMBUFn");
  1596. memset(&vm, 0 , sizeof(vm));
  1597. vm.size = PLANB_MAX_FBUF * MAX_GBUFFERS;
  1598. vm.frames = MAX_GBUFFERS;
  1599. for(i = 0; i<MAX_GBUFFERS; i++)
  1600. vm.offsets[i] = PLANB_MAX_FBUF * i;
  1601. if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
  1602. return -EFAULT;
  1603. return 0;
  1604. }
  1605. case PLANBIOCGSAAREGS:
  1606. {
  1607. struct planb_saa_regs preg;
  1608. DEBUG("PlanB: IOCTL PLANBIOCGSAAREGSn");
  1609. if(copy_from_user(&preg, arg, sizeof(preg)))
  1610. return -EFAULT;
  1611. if(preg.addr >= SAA7196_NUMREGS)
  1612. return -EINVAL;
  1613. preg.val = saa_regs[pb->win.norm][preg.addr];
  1614. if(copy_to_user((void *)arg, (void *)&preg,
  1615. sizeof(preg)))
  1616. return -EFAULT;
  1617. return 0;
  1618. }
  1619. case PLANBIOCSSAAREGS:
  1620. {
  1621. struct planb_saa_regs preg;
  1622. DEBUG("PlanB: IOCTL PLANBIOCSSAAREGSn");
  1623. if(copy_from_user(&preg, arg, sizeof(preg)))
  1624. return -EFAULT;
  1625. if(preg.addr >= SAA7196_NUMREGS)
  1626. return -EINVAL;
  1627. saa_set (preg.addr, preg.val, pb);
  1628. return 0;
  1629. }
  1630. case PLANBIOCGSTAT:
  1631. {
  1632. struct planb_stat_regs pstat;
  1633. DEBUG("PlanB: IOCTL PLANBIOCGSTATn");
  1634. pstat.ch1_stat = in_le32(&pb->planb_base->ch1.status);
  1635. pstat.ch2_stat = in_le32(&pb->planb_base->ch2.status);
  1636. pstat.saa_stat0 = saa_status(0, pb);
  1637. pstat.saa_stat1 = saa_status(1, pb);
  1638. if(copy_to_user((void *)arg, (void *)&pstat,
  1639. sizeof(pstat)))
  1640. return -EFAULT;
  1641. return 0;
  1642. }
  1643. case PLANBIOCSMODE: {
  1644. int v;
  1645. DEBUG("PlanB: IOCTL PLANBIOCSMODEn");
  1646. if(copy_from_user(&v, arg, sizeof(v)))
  1647. return -EFAULT;
  1648. switch(v)
  1649. {
  1650. case PLANB_TV_MODE:
  1651. saa_set (SAA7196_STDC,
  1652. (saa_regs[pb->win.norm][SAA7196_STDC] &
  1653.   0x7f), pb);
  1654. break;
  1655. case PLANB_VTR_MODE:
  1656. saa_set (SAA7196_STDC,
  1657. (saa_regs[pb->win.norm][SAA7196_STDC] |
  1658.   0x80), pb);
  1659. break;
  1660. default:
  1661. return -EINVAL;
  1662. break;
  1663. }
  1664. pb->win.mode = v;
  1665. return 0;
  1666. }
  1667. case PLANBIOCGMODE: {
  1668. int v=pb->win.mode;
  1669. DEBUG("PlanB: IOCTL PLANBIOCGMODEn");
  1670. if(copy_to_user(arg,&v,sizeof(v)))
  1671. return -EFAULT;
  1672. return 0;
  1673. }
  1674. #ifdef PLANB_GSCANLINE
  1675. case PLANBG_GRAB_BPL: {
  1676. int v=pb->gbytes_per_line;
  1677. DEBUG("PlanB: IOCTL PLANBG_GRAB_BPLn");
  1678. if(copy_to_user(arg,&v,sizeof(v)))
  1679. return -EFAULT;
  1680. return 0;
  1681. }
  1682. #endif /* PLANB_GSCANLINE */
  1683. case PLANB_INTR_DEBUG: {
  1684. int i;
  1685. DEBUG("PlanB: IOCTL PLANB_INTR_DEBUGn");
  1686. if(copy_from_user(&i, arg, sizeof(i)))
  1687. return -EFAULT;
  1688. /* avoid hang ups all together */
  1689. for (i = 0; i < MAX_GBUFFERS; i++) {
  1690. if(pb->frame_stat[i] == GBUFFER_GRABBING) {
  1691. pb->frame_stat[i] = GBUFFER_DONE;
  1692. }
  1693. }
  1694. if(pb->grabbing)
  1695. pb->grabbing--;
  1696. wake_up_interruptible(&pb->capq);
  1697. return 0;
  1698. }
  1699. case PLANB_INV_REGS: {
  1700. int i;
  1701. struct planb_any_regs any;
  1702. DEBUG("PlanB: IOCTL PLANB_INV_REGSn");
  1703. if(copy_from_user(&any, arg, sizeof(any)))
  1704. return -EFAULT;
  1705. if(any.offset < 0 || any.offset + any.bytes > 0x400)
  1706. return -EINVAL;
  1707. if(any.bytes > 128)
  1708. return -EINVAL;
  1709. for (i = 0; i < any.bytes; i++) {
  1710. any.data[i] =
  1711. in_8((unsigned char *)pb->planb_base
  1712. + any.offset + i);
  1713. }
  1714. if(copy_to_user(arg,&any,sizeof(any)))
  1715. return -EFAULT;
  1716. return 0;
  1717. }
  1718. default:
  1719. {
  1720. DEBUG("PlanB: Unimplemented IOCTLn");
  1721. return -ENOIOCTLCMD;
  1722. }
  1723. /* Some IOCTLs are currently unsupported on PlanB */
  1724. case VIDIOCGTUNER: {
  1725. DEBUG("PlanB: IOCTL VIDIOCGTUNERn");
  1726. goto unimplemented; }
  1727. case VIDIOCSTUNER: {
  1728. DEBUG("PlanB: IOCTL VIDIOCSTUNERn");
  1729. goto unimplemented; }
  1730. case VIDIOCSFREQ: {
  1731. DEBUG("PlanB: IOCTL VIDIOCSFREQn");
  1732. goto unimplemented; }
  1733. case VIDIOCGFREQ: {
  1734. DEBUG("PlanB: IOCTL VIDIOCGFREQn");
  1735. goto unimplemented; }
  1736. case VIDIOCKEY: {
  1737. DEBUG("PlanB: IOCTL VIDIOCKEYn");
  1738. goto unimplemented; }
  1739. case VIDIOCSAUDIO: {
  1740. DEBUG("PlanB: IOCTL VIDIOCSAUDIOn");
  1741. goto unimplemented; }
  1742. case VIDIOCGAUDIO: {
  1743. DEBUG("PlanB: IOCTL VIDIOCGAUDIOn");
  1744. goto unimplemented; }
  1745. unimplemented:
  1746. DEBUG("       Unimplementedn");
  1747. return -ENOIOCTLCMD;
  1748. }
  1749. return 0;
  1750. }
  1751. static int planb_mmap(struct video_device *dev, const char *adr, unsigned long size)
  1752. {
  1753. int i;
  1754. struct planb *pb = (struct planb *)dev;
  1755.         unsigned long start = (unsigned long)adr;
  1756. if (size > MAX_GBUFFERS * PLANB_MAX_FBUF)
  1757.         return -EINVAL;
  1758. if (!pb->rawbuf) {
  1759. int err;
  1760. if((err=grabbuf_alloc(pb)))
  1761. return err;
  1762. }
  1763. for (i = 0; i < pb->rawbuf_size; i++) {
  1764. if (remap_page_range(start, virt_to_phys((void *)pb->rawbuf[i]),
  1765. PAGE_SIZE, PAGE_SHARED))
  1766. return -EAGAIN;
  1767. start += PAGE_SIZE;
  1768. if (size <= PAGE_SIZE)
  1769. break;
  1770. size -= PAGE_SIZE;
  1771. }
  1772. return 0;
  1773. }
  1774. static struct video_device planb_template=
  1775. {
  1776. owner: THIS_MODULE,
  1777. name: PLANB_DEVICE_NAME,
  1778. type: VID_TYPE_OVERLAY,
  1779. hardware: VID_HARDWARE_PLANB,
  1780. open: planb_open,
  1781. close: planb_close,
  1782. read: planb_read,
  1783. write: planb_write,
  1784. ioctl: planb_ioctl,
  1785. mmap: planb_mmap, /* mmap? */
  1786. };
  1787. static int init_planb(struct planb *pb)
  1788. {
  1789. unsigned char saa_rev;
  1790. int i, result;
  1791. unsigned long flags;
  1792. memset ((void *) &pb->win, 0, sizeof (struct planb_window));
  1793. /* Simple sanity check */
  1794. if(def_norm >= NUM_SUPPORTED_NORM || def_norm < 0) {
  1795. printk(KERN_ERR "PlanB: Option(s) invalidn");
  1796. return -2;
  1797. }
  1798. pb->win.norm = def_norm;
  1799. pb->win.mode = PLANB_TV_MODE; /* TV mode */
  1800. pb->win.interlace=1;
  1801. pb->win.x=0;
  1802. pb->win.y=0;
  1803. pb->win.width=768; /* 640 */
  1804. pb->win.height=576; /* 480 */
  1805. pb->maxlines=576;
  1806. #if 0
  1807. btv->win.cropwidth=768; /* 640 */
  1808. btv->win.cropheight=576; /* 480 */
  1809. btv->win.cropx=0;
  1810. btv->win.cropy=0;
  1811. #endif
  1812. pb->win.pad=0;
  1813. pb->win.bpp=4;
  1814. pb->win.depth=32;
  1815. pb->win.color_fmt=PLANB_COLOUR32;
  1816. pb->win.bpl=1024*pb->win.bpp;
  1817. pb->win.swidth=1024;
  1818. pb->win.sheight=768;
  1819. #ifdef PLANB_GSCANLINE
  1820. if((pb->gbytes_per_line = PLANB_MAXPIXELS * 4) > PAGE_SIZE
  1821. || (pb->gbytes_per_line <= 0))
  1822. return -3;
  1823. else {
  1824. /* page align pb->gbytes_per_line for DMA purpose */
  1825. for(i = PAGE_SIZE; pb->gbytes_per_line < (i>>1);)
  1826. i>>=1;
  1827. pb->gbytes_per_line = i;
  1828. }
  1829. #endif
  1830. pb->tab_size = PLANB_MAXLINES + 40;
  1831. pb->suspend = 0;
  1832. init_MUTEX(&pb->lock);
  1833. pb->ch1_cmd = 0;
  1834. pb->ch2_cmd = 0;
  1835. pb->mask = 0;
  1836. pb->priv_space = 0;
  1837. pb->offset = 0;
  1838. pb->user = 0;
  1839. pb->overlay = 0;
  1840. init_waitqueue_head(&pb->suspendq);
  1841. pb->cmd_buff_inited = 0;
  1842. pb->frame_buffer_phys = 0;
  1843. /* Reset DMA controllers */
  1844. planb_dbdma_stop(&pb->planb_base->ch2);
  1845. planb_dbdma_stop(&pb->planb_base->ch1);
  1846. saa_rev =  (saa_status(0, pb) & 0xf0) >> 4;
  1847. printk(KERN_INFO "PlanB: SAA7196 video processor rev. %dn", saa_rev);
  1848. /* Initialize the SAA registers in memory and on chip */
  1849. saa_init_regs (pb);
  1850. /* clear interrupt mask */
  1851. pb->intr_mask = PLANB_CLR_IRQ;
  1852. save_flags(flags); cli();
  1853.         result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb);
  1854.         if (result < 0) {
  1855.         if (result==-EINVAL)
  1856.                 printk(KERN_ERR "PlanB: Bad irq number (%d) "
  1857. "or handlern", (int)pb->irq);
  1858. else if (result==-EBUSY)
  1859. printk(KERN_ERR "PlanB: I don't know why, "
  1860. "but IRQ %d is busyn", (int)pb->irq);
  1861. restore_flags(flags);
  1862. return result;
  1863. }
  1864. disable_irq(pb->irq);
  1865. restore_flags(flags);
  1866.         
  1867. /* Now add the template and register the device unit. */
  1868. memcpy(&pb->video_dev,&planb_template,sizeof(planb_template));
  1869. pb->picture.brightness=0x90<<8;
  1870. pb->picture.contrast = 0x70 << 8;
  1871. pb->picture.colour = 0x70<<8;
  1872. pb->picture.hue = 0x8000;
  1873. pb->picture.whiteness = 0;
  1874. pb->picture.depth = pb->win.depth;
  1875. pb->frame_stat=NULL;
  1876. init_waitqueue_head(&pb->capq);
  1877. for(i=0; i<MAX_GBUFFERS; i++) {
  1878. pb->gbuf_idx[i] = PLANB_MAX_FBUF * i / PAGE_SIZE;
  1879. pb->gwidth[i]=0;
  1880. pb->gheight[i]=0;
  1881. pb->gfmt[i]=0;
  1882. pb->cap_cmd[i]=NULL;
  1883. #ifndef PLANB_GSCANLINE
  1884. pb->l_fr_addr_idx[i] = MAX_GBUFFERS * (PLANB_MAX_FBUF
  1885. / PAGE_SIZE + 1) + MAX_LNUM * i;
  1886. pb->lsize[i] = 0;
  1887. pb->lnum[i] = 0;
  1888. #endif
  1889. }
  1890. pb->rawbuf=NULL;
  1891. pb->grabbing=0;
  1892. /* enable interrupts */
  1893. out_le32(&pb->planb_base->intr_stat, PLANB_CLR_IRQ);
  1894. pb->intr_mask = PLANB_FRM_IRQ;
  1895. enable_irq(pb->irq);
  1896. if(video_register_device(&pb->video_dev, VFL_TYPE_GRABBER, video_nr)<0)
  1897. return -1;
  1898. return 0;
  1899. }
  1900. /*
  1901.  * Scan for a PlanB controller, request the irq and map the io memory 
  1902.  */
  1903. static int find_planb(void)
  1904. {
  1905. struct planb *pb;
  1906. struct device_node *planb_devices;
  1907. unsigned char dev_fn, confreg, bus;
  1908. unsigned int old_base, new_base;
  1909. unsigned int irq;
  1910. struct pci_dev  *pdev;
  1911. if (_machine != _MACH_Pmac)
  1912. return 0;
  1913. planb_devices = find_devices("planb");
  1914. if (planb_devices == 0) {
  1915. planb_num=0;
  1916. printk(KERN_WARNING "PlanB: no device found!n");
  1917. return planb_num;
  1918. }
  1919. if (planb_devices->next != NULL)
  1920. printk(KERN_ERR "Warning: only using first PlanB device!n");
  1921. pb = &planbs[0];
  1922. planb_num = 1;
  1923.         if (planb_devices->n_addrs != 1) {
  1924.                 printk (KERN_WARNING "PlanB: expecting 1 address for planb "
  1925.                  "(got %d)", planb_devices->n_addrs);
  1926. return 0;
  1927. }
  1928. if (planb_devices->n_intrs == 0) {
  1929. printk(KERN_WARNING "PlanB: no intrs for device %sn",
  1930.        planb_devices->full_name);
  1931. return 0;
  1932. } else {
  1933. irq = planb_devices->intrs[0].line;
  1934. }
  1935. /* Initialize PlanB's PCI registers */
  1936. /* There is a bug with the way OF assigns addresses
  1937.    to the devices behind the chaos bridge.
  1938.    control needs only 0x1000 of space, but decodes only
  1939.    the upper 16 bits. It therefore occupies a full 64K.
  1940.    OF assigns the planb controller memory within this space;
  1941.    so we need to change that here in order to access planb. */
  1942. /* We remap to 0xf1000000 in hope that nobody uses it ! */
  1943. bus = (planb_devices->addrs[0].space >> 16) & 0xff;
  1944. dev_fn = (planb_devices->addrs[0].space >> 8) & 0xff;
  1945. confreg = planb_devices->addrs[0].space & 0xff;
  1946. old_base = planb_devices->addrs[0].address;
  1947. new_base = 0xf1000000;
  1948. DEBUG("PlanB: Found on bus %d, dev %d, func %d, "
  1949. "membase 0x%x (base reg. 0x%x)n",
  1950. bus, PCI_SLOT(dev_fn), PCI_FUNC(dev_fn), old_base, confreg);
  1951. pdev = pci_find_slot (bus, dev_fn);
  1952. if (!pdev) {
  1953. printk(KERN_ERR "cannot find slotn");
  1954. /* XXX handle error */
  1955. }
  1956. /* Enable response in memory space, bus mastering,
  1957.    use memory write and invalidate */
  1958. pci_write_config_word (pdev, PCI_COMMAND,
  1959. PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
  1960. PCI_COMMAND_INVALIDATE);
  1961. /* Set PCI Cache line size & latency timer */
  1962. pci_write_config_byte (pdev, PCI_CACHE_LINE_SIZE, 0x8);
  1963. pci_write_config_byte (pdev, PCI_LATENCY_TIMER, 0x40);
  1964. /* Set the new base address */
  1965. pci_write_config_dword (pdev, confreg, new_base);
  1966. planb_regs = (volatile struct planb_registers *)
  1967. ioremap (new_base, 0x400);
  1968. pb->planb_base = planb_regs;
  1969. pb->planb_base_phys = (struct planb_registers *)new_base;
  1970. pb->irq = irq;
  1971. return planb_num;
  1972. }
  1973. static void release_planb(void)
  1974. {
  1975. int i;
  1976. struct planb *pb;
  1977. for (i=0;i<planb_num; i++) 
  1978. {
  1979. pb=&planbs[i];
  1980. /* stop and flash DMAs unconditionally */
  1981. planb_dbdma_stop(&pb->planb_base->ch2);
  1982. planb_dbdma_stop(&pb->planb_base->ch1);
  1983. /* clear and free interrupts */
  1984. pb->intr_mask = PLANB_CLR_IRQ;
  1985. out_le32 (&pb->planb_base->intr_stat, PLANB_CLR_IRQ);
  1986. free_irq(pb->irq, pb);
  1987. /* make sure all allocated memory are freed */
  1988. planb_prepare_close(pb);
  1989. printk(KERN_INFO "PlanB: unregistering with v4ln");
  1990. video_unregister_device(&pb->video_dev);
  1991. /* note that iounmap() does nothing on the PPC right now */
  1992. iounmap ((void *)pb->planb_base);
  1993. }
  1994. }
  1995. static int __init init_planbs(void)
  1996. {
  1997. int i;
  1998.   
  1999. if (find_planb()<=0)
  2000. return -EIO;
  2001. for (i=0; i<planb_num; i++) {
  2002. if (init_planb(&planbs[i])<0) {
  2003. printk(KERN_ERR "PlanB: error registering device %d"
  2004. " with v4ln", i);
  2005. release_planb();
  2006. return -EIO;
  2007. printk(KERN_INFO "PlanB: registered device %d with v4ln", i);
  2008. }  
  2009. return 0;
  2010. }
  2011. static void __exit exit_planbs(void)
  2012. {
  2013. release_planb();
  2014. }
  2015. module_init(init_planbs);
  2016. module_exit(exit_planbs);