2 planb - PlanB frame grabber driver
4 PlanB is used in the 7x00/8x00 series of PowerMacintosh
5 Computers as video input DMA controller.
7 Copyright (C) 1998 Michel Lanners (mlan@cpu.lu)
9 Based largely on the bttv driver by Ralph Metzler (rjkm@thp.uni-koeln.de)
11 Additional debugging and coding by Takashi Oe (toe@unlserve.unl.edu)
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 /* $Id: planb.c,v 1.18 1999/05/02 17:36:34 mlan Exp $ */
30 #include <linux/init.h>
31 #include <linux/errno.h>
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/major.h>
35 #include <linux/slab.h>
36 #include <linux/types.h>
37 #include <linux/pci.h>
38 #include <linux/delay.h>
39 #include <linux/vmalloc.h>
41 #include <linux/sched.h>
42 #include <linux/videodev.h>
43 #include <media/v4l2-common.h>
44 #include <linux/wait.h>
45 #include <asm/uaccess.h>
48 #include <asm/dbdma.h>
49 #include <asm/pgtable.h>
52 #include <linux/mutex.h>
57 /* Would you mind for some ugly debugging? */
59 #define DEBUG(x...) printk(KERN_DEBUG ## x) /* Debug driver */
61 #define DEBUG(x...) /* Don't debug driver */
65 #define IDEBUG(x...) printk(KERN_DEBUG ## x) /* Debug interrupt part */
67 #define IDEBUG(x...) /* Don't debug interrupt part */
70 /* Ever seen a Mac with more than 1 of these? */
74 static struct planb planbs
[PLANB_MAX
];
75 static volatile struct planb_registers
*planb_regs
;
77 static int def_norm
= PLANB_DEF_NORM
; /* default norm */
78 static int video_nr
= -1;
80 module_param(def_norm
, int, 0);
81 MODULE_PARM_DESC(def_norm
, "Default startup norm (0=PAL, 1=NTSC, 2=SECAM)");
82 module_param(video_nr
, int, 0);
83 MODULE_LICENSE("GPL");
86 /* ------------------ PlanB Exported Functions ------------------ */
87 static long planb_write(struct video_device
*, const char *, unsigned long, int);
88 static long planb_read(struct video_device
*, char *, unsigned long, int);
89 static int planb_open(struct video_device
*, int);
90 static void planb_close(struct video_device
*);
91 static int planb_ioctl(struct video_device
*, unsigned int, void *);
92 static int planb_init_done(struct video_device
*);
93 static int planb_mmap(struct video_device
*, const char *, unsigned long);
94 static void planb_irq(int, void *);
95 static void release_planb(void);
96 int init_planbs(struct video_init
*);
98 /* ------------------ PlanB Internal Functions ------------------ */
99 static int planb_prepare_open(struct planb
*);
100 static void planb_prepare_close(struct planb
*);
101 static void saa_write_reg(unsigned char, unsigned char);
102 static unsigned char saa_status(int, struct planb
*);
103 static void saa_set(unsigned char, unsigned char, struct planb
*);
104 static void saa_init_regs(struct planb
*);
105 static int grabbuf_alloc(struct planb
*);
106 static int vgrab(struct planb
*, struct video_mmap
*);
107 static void add_clip(struct planb
*, struct video_clip
*);
108 static void fill_cmd_buff(struct planb
*);
109 static void cmd_buff(struct planb
*);
110 static volatile struct dbdma_cmd
*setup_grab_cmd(int, struct planb
*);
111 static void overlay_start(struct planb
*);
112 static void overlay_stop(struct planb
*);
113 static inline void tab_cmd_dbdma(volatile struct dbdma_cmd
*, unsigned short,
115 static inline void tab_cmd_store(volatile struct dbdma_cmd
*, unsigned int,
117 static inline void tab_cmd_gen(volatile struct dbdma_cmd
*, unsigned short,
118 unsigned short, unsigned int, unsigned int);
119 static int init_planb(struct planb
*);
120 static int find_planb(void);
121 static void planb_pre_capture(int, int, struct planb
*);
122 static volatile struct dbdma_cmd
*cmd_geo_setup(volatile struct dbdma_cmd
*,
123 int, int, int, int, int, struct planb
*);
124 static inline void planb_dbdma_stop(volatile struct dbdma_regs
*);
125 static unsigned int saa_geo_setup(int, int, int, int, struct planb
*);
126 static inline int overlay_is_active(struct planb
*);
128 /*******************************/
129 /* Memory management functions */
130 /*******************************/
132 static int grabbuf_alloc(struct planb
*pb
)
136 npage
= MAX_GBUFFERS
* ((PLANB_MAX_FBUF
/ PAGE_SIZE
+ 1)
137 #ifndef PLANB_GSCANLINE
139 #endif /* PLANB_GSCANLINE */
141 if ((pb
->rawbuf
= kmalloc(npage
142 * sizeof(unsigned long), GFP_KERNEL
)) == 0)
144 for (i
= 0; i
< npage
; i
++) {
145 pb
->rawbuf
[i
] = (unsigned char *)__get_free_pages(GFP_KERNEL
149 SetPageReserved(virt_to_page(pb
->rawbuf
[i
]));
152 printk(KERN_DEBUG
"PlanB: init_grab: grab buffer not allocated\n");
154 ClearPageReserved(virt_to_page(pb
->rawbuf
[i
]));
155 free_pages((unsigned long)pb
->rawbuf
[i
], 0);
160 pb
->rawbuf_size
= npage
;
164 /*****************************/
165 /* Hardware access functions */
166 /*****************************/
168 static void saa_write_reg(unsigned char addr
, unsigned char val
)
170 planb_regs
->saa_addr
= addr
; eieio();
171 planb_regs
->saa_regval
= val
; eieio();
175 /* return status byte 0 or 1: */
176 static unsigned char saa_status(int byte
, struct planb
*pb
)
178 saa_regs
[pb
->win
.norm
][SAA7196_STDC
] =
179 (saa_regs
[pb
->win
.norm
][SAA7196_STDC
] & ~2) | ((byte
& 1) << 1);
180 saa_write_reg (SAA7196_STDC
, saa_regs
[pb
->win
.norm
][SAA7196_STDC
]);
182 /* Let's wait 30msec for this one */
183 msleep_interruptible(30);
185 return (unsigned char)in_8 (&planb_regs
->saa_status
);
188 static void saa_set(unsigned char addr
, unsigned char val
, struct planb
*pb
)
190 if(saa_regs
[pb
->win
.norm
][addr
] != val
) {
191 saa_regs
[pb
->win
.norm
][addr
] = val
;
192 saa_write_reg (addr
, val
);
197 static void saa_init_regs(struct planb
*pb
)
201 for (i
= 0; i
< SAA7196_NUMREGS
; i
++)
202 saa_write_reg (i
, saa_regs
[pb
->win
.norm
][i
]);
205 static unsigned int saa_geo_setup(int width
, int height
, int interlace
, int bpp
,
208 int ht
, norm
= pb
->win
.norm
;
212 /* RGB555+a 1x16-bit + 16-bit transparent */
213 saa_regs
[norm
][SAA7196_FMTS
] &= ~0x3;
217 /* RGB888 1x24-bit + 8-bit transparent */
218 saa_regs
[norm
][SAA7196_FMTS
] &= ~0x1;
219 saa_regs
[norm
][SAA7196_FMTS
] |= 0x2;
224 ht
= (interlace
? height
/ 2 : height
);
225 saa_regs
[norm
][SAA7196_OUTPIX
] = (unsigned char) (width
& 0x00ff);
226 saa_regs
[norm
][SAA7196_HFILT
] = (saa_regs
[norm
][SAA7196_HFILT
] & ~0x3)
227 | (width
>> 8 & 0x3);
228 saa_regs
[norm
][SAA7196_OUTLINE
] = (unsigned char) (ht
& 0xff);
229 saa_regs
[norm
][SAA7196_VYP
] = (saa_regs
[norm
][SAA7196_VYP
] & ~0x3)
231 /* feed both fields if interlaced, or else feed only even fields */
232 saa_regs
[norm
][SAA7196_FMTS
] = (interlace
) ?
233 (saa_regs
[norm
][SAA7196_FMTS
] & ~0x60)
234 : (saa_regs
[norm
][SAA7196_FMTS
] | 0x60);
235 /* transparent mode; extended format enabled */
236 saa_regs
[norm
][SAA7196_DPATH
] |= 0x3;
241 /***************************/
242 /* DBDMA support functions */
243 /***************************/
245 static inline void planb_dbdma_restart(volatile struct dbdma_regs
*ch
)
247 out_le32(&ch
->control
, PLANB_CLR(RUN
));
248 out_le32(&ch
->control
, PLANB_SET(RUN
|WAKE
) | PLANB_CLR(PAUSE
));
251 static inline void planb_dbdma_stop(volatile struct dbdma_regs
*ch
)
255 out_le32(&ch
->control
, PLANB_CLR(RUN
) | PLANB_SET(FLUSH
));
256 while((in_le32(&ch
->status
) == (ACTIVE
| FLUSH
)) && (i
< 999)) {
257 IDEBUG("PlanB: waiting for DMA to stop\n");
262 static inline void tab_cmd_dbdma(volatile struct dbdma_cmd
*ch
,
263 unsigned short command
, unsigned int cmd_dep
)
265 st_le16(&ch
->command
, command
);
266 st_le32(&ch
->cmd_dep
, cmd_dep
);
269 static inline void tab_cmd_store(volatile struct dbdma_cmd
*ch
,
270 unsigned int phy_addr
, unsigned int cmd_dep
)
272 st_le16(&ch
->command
, STORE_WORD
| KEY_SYSTEM
);
273 st_le16(&ch
->req_count
, 4);
274 st_le32(&ch
->phy_addr
, phy_addr
);
275 st_le32(&ch
->cmd_dep
, cmd_dep
);
278 static inline void tab_cmd_gen(volatile struct dbdma_cmd
*ch
,
279 unsigned short command
, unsigned short req_count
,
280 unsigned int phy_addr
, unsigned int cmd_dep
)
282 st_le16(&ch
->command
, command
);
283 st_le16(&ch
->req_count
, req_count
);
284 st_le32(&ch
->phy_addr
, phy_addr
);
285 st_le32(&ch
->cmd_dep
, cmd_dep
);
288 static volatile struct dbdma_cmd
*cmd_geo_setup(
289 volatile struct dbdma_cmd
*c1
, int width
, int height
, int interlace
,
290 int bpp
, int clip
, struct planb
*pb
)
292 int norm
= pb
->win
.norm
;
294 if((saa_geo_setup(width
, height
, interlace
, bpp
, pb
)) != 0)
295 return (volatile struct dbdma_cmd
*)NULL
;
296 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->saa_addr
),
298 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->saa_regval
),
299 saa_regs
[norm
][SAA7196_FMTS
]);
300 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->saa_addr
),
302 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->saa_regval
),
303 saa_regs
[norm
][SAA7196_DPATH
]);
304 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->even
),
305 bpp
| ((clip
)? PLANB_CLIPMASK
: 0));
306 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->odd
),
307 bpp
| ((clip
)? PLANB_CLIPMASK
: 0));
308 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->saa_addr
),
310 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->saa_regval
),
311 saa_regs
[norm
][SAA7196_OUTPIX
]);
312 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->saa_addr
),
314 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->saa_regval
),
315 saa_regs
[norm
][SAA7196_HFILT
]);
316 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->saa_addr
),
318 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->saa_regval
),
319 saa_regs
[norm
][SAA7196_OUTLINE
]);
320 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->saa_addr
),
322 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->saa_regval
),
323 saa_regs
[norm
][SAA7196_VYP
]);
327 /******************************/
328 /* misc. supporting functions */
329 /******************************/
331 static inline void planb_lock(struct planb
*pb
)
333 mutex_lock(&pb
->lock
);
336 static inline void planb_unlock(struct planb
*pb
)
338 mutex_unlock(&pb
->lock
);
345 static int planb_prepare_open(struct planb
*pb
)
349 /* allocate memory for two plus alpha command buffers (size: max lines,
350 plus 40 commands handling, plus 1 alignment), plus dummy command buf,
351 plus clipmask buffer, plus frame grabbing status */
352 size
= (pb
->tab_size
*(2+MAX_GBUFFERS
*TAB_FACTOR
)+1+MAX_GBUFFERS
353 * PLANB_DUMMY
)*sizeof(struct dbdma_cmd
)
354 +(PLANB_MAXLINES
*((PLANB_MAXPIXELS
+7)& ~7))/8
355 +MAX_GBUFFERS
*sizeof(unsigned int);
356 if ((pb
->priv_space
= kmalloc (size
, GFP_KERNEL
)) == 0)
358 memset ((void *) pb
->priv_space
, 0, size
);
359 pb
->overlay_last1
= pb
->ch1_cmd
= (volatile struct dbdma_cmd
*)
360 DBDMA_ALIGN (pb
->priv_space
);
361 pb
->overlay_last2
= pb
->ch2_cmd
= pb
->ch1_cmd
+ pb
->tab_size
;
362 pb
->ch1_cmd_phys
= virt_to_bus(pb
->ch1_cmd
);
363 pb
->cap_cmd
[0] = pb
->ch2_cmd
+ pb
->tab_size
;
364 pb
->pre_cmd
[0] = pb
->cap_cmd
[0] + pb
->tab_size
* TAB_FACTOR
;
365 for (i
= 1; i
< MAX_GBUFFERS
; i
++) {
366 pb
->cap_cmd
[i
] = pb
->pre_cmd
[i
-1] + PLANB_DUMMY
;
367 pb
->pre_cmd
[i
] = pb
->cap_cmd
[i
] + pb
->tab_size
* TAB_FACTOR
;
369 pb
->frame_stat
=(volatile unsigned int *)(pb
->pre_cmd
[MAX_GBUFFERS
-1]
371 pb
->mask
= (unsigned char *)(pb
->frame_stat
+MAX_GBUFFERS
);
376 for (i
= 0; i
< MAX_GBUFFERS
; i
++) {
377 pb
->frame_stat
[i
] = GBUFFER_UNUSED
;
381 pb
->gnorm_switch
[i
] = 0;
382 #ifndef PLANB_GSCANLINE
385 #endif /* PLANB_GSCANLINE */
390 pb
->prev_last_fr
= -999;
392 /* Reset DMA controllers */
393 planb_dbdma_stop(&pb
->planb_base
->ch2
);
394 planb_dbdma_stop(&pb
->planb_base
->ch1
);
399 static void planb_prepare_close(struct planb
*pb
)
403 /* make sure the dma's are idle */
404 planb_dbdma_stop(&pb
->planb_base
->ch2
);
405 planb_dbdma_stop(&pb
->planb_base
->ch1
);
406 /* free kernel memory of command buffers */
407 if(pb
->priv_space
!= 0) {
408 kfree (pb
->priv_space
);
410 pb
->cmd_buff_inited
= 0;
413 for (i
= 0; i
< pb
->rawbuf_size
; i
++) {
414 ClearPageReserved(virt_to_page(pb
->rawbuf
[i
]));
415 free_pages((unsigned long)pb
->rawbuf
[i
], 0);
422 /*****************************/
423 /* overlay support functions */
424 /*****************************/
426 static inline int overlay_is_active(struct planb
*pb
)
428 unsigned int size
= pb
->tab_size
* sizeof(struct dbdma_cmd
);
429 unsigned int caddr
= (unsigned)in_le32(&pb
->planb_base
->ch1
.cmdptr
);
431 return (in_le32(&pb
->overlay_last1
->cmd_dep
) == pb
->ch1_cmd_phys
)
432 && (caddr
< (pb
->ch1_cmd_phys
+ size
))
433 && (caddr
>= (unsigned)pb
->ch1_cmd_phys
);
436 static void overlay_start(struct planb
*pb
)
439 DEBUG("PlanB: overlay_start()\n");
441 if(ACTIVE
& in_le32(&pb
->planb_base
->ch1
.status
)) {
443 DEBUG("PlanB: presumably, grabbing is in progress...\n");
445 planb_dbdma_stop(&pb
->planb_base
->ch2
);
446 out_le32 (&pb
->planb_base
->ch2
.cmdptr
,
447 virt_to_bus(pb
->ch2_cmd
));
448 planb_dbdma_restart(&pb
->planb_base
->ch2
);
449 st_le16 (&pb
->ch1_cmd
->command
, DBDMA_NOP
);
450 tab_cmd_dbdma(pb
->last_cmd
[pb
->last_fr
],
451 DBDMA_NOP
| BR_ALWAYS
,
452 virt_to_bus(pb
->ch1_cmd
));
454 pb
->prev_last_fr
= pb
->last_fr
;
456 if(!(ACTIVE
& in_le32(&pb
->planb_base
->ch1
.status
))) {
457 IDEBUG("PlanB: became inactive "
458 "in the mean time... reactivating\n");
459 planb_dbdma_stop(&pb
->planb_base
->ch1
);
460 out_le32 (&pb
->planb_base
->ch1
.cmdptr
,
461 virt_to_bus(pb
->ch1_cmd
));
462 planb_dbdma_restart(&pb
->planb_base
->ch1
);
466 DEBUG("PlanB: currently idle, so can do whatever\n");
468 planb_dbdma_stop(&pb
->planb_base
->ch2
);
469 planb_dbdma_stop(&pb
->planb_base
->ch1
);
470 st_le32 (&pb
->planb_base
->ch2
.cmdptr
,
471 virt_to_bus(pb
->ch2_cmd
));
472 st_le32 (&pb
->planb_base
->ch1
.cmdptr
,
473 virt_to_bus(pb
->ch1_cmd
));
474 out_le16 (&pb
->ch1_cmd
->command
, DBDMA_NOP
);
475 planb_dbdma_restart(&pb
->planb_base
->ch2
);
476 planb_dbdma_restart(&pb
->planb_base
->ch1
);
482 static void overlay_stop(struct planb
*pb
)
484 DEBUG("PlanB: overlay_stop()\n");
486 if(pb
->last_fr
== -1) {
488 DEBUG("PlanB: no grabbing, it seems...\n");
490 planb_dbdma_stop(&pb
->planb_base
->ch2
);
491 planb_dbdma_stop(&pb
->planb_base
->ch1
);
493 } else if(pb
->last_fr
== -2) {
494 unsigned int cmd_dep
;
495 tab_cmd_dbdma(pb
->cap_cmd
[pb
->prev_last_fr
], DBDMA_STOP
, 0);
497 cmd_dep
= (unsigned int)in_le32(&pb
->overlay_last1
->cmd_dep
);
498 if(overlay_is_active(pb
)) {
500 DEBUG("PlanB: overlay is currently active\n");
502 planb_dbdma_stop(&pb
->planb_base
->ch2
);
503 planb_dbdma_stop(&pb
->planb_base
->ch1
);
504 if(cmd_dep
!= pb
->ch1_cmd_phys
) {
505 out_le32(&pb
->planb_base
->ch1
.cmdptr
,
506 virt_to_bus(pb
->overlay_last1
));
507 planb_dbdma_restart(&pb
->planb_base
->ch1
);
510 pb
->last_fr
= pb
->prev_last_fr
;
511 pb
->prev_last_fr
= -999;
516 static void suspend_overlay(struct planb
*pb
)
519 struct dbdma_cmd last
;
521 DEBUG("PlanB: suspend_overlay: %d\n", pb
->suspend
);
525 if(ACTIVE
& in_le32(&pb
->planb_base
->ch1
.status
)) {
526 if(pb
->last_fr
== -2) {
527 fr
= pb
->prev_last_fr
;
528 memcpy(&last
, (void*)pb
->last_cmd
[fr
], sizeof(last
));
529 tab_cmd_dbdma(pb
->last_cmd
[fr
], DBDMA_STOP
, 0);
531 if(overlay_is_active(pb
)) {
532 planb_dbdma_stop(&pb
->planb_base
->ch2
);
533 planb_dbdma_stop(&pb
->planb_base
->ch1
);
534 pb
->suspended
.overlay
= 1;
535 pb
->suspended
.frame
= fr
;
536 memcpy(&pb
->suspended
.cmd
, &last
, sizeof(last
));
540 pb
->suspended
.overlay
= 0;
541 pb
->suspended
.frame
= fr
;
542 memcpy(&pb
->suspended
.cmd
, &last
, sizeof(last
));
546 static void resume_overlay(struct planb
*pb
)
549 DEBUG("PlanB: resume_overlay: %d\n", pb
->suspend
);
553 if(pb
->suspended
.frame
!= -1) {
554 memcpy((void*)pb
->last_cmd
[pb
->suspended
.frame
],
555 &pb
->suspended
.cmd
, sizeof(pb
->suspended
.cmd
));
557 if(ACTIVE
& in_le32(&pb
->planb_base
->ch1
.status
)) {
560 if(pb
->suspended
.overlay
) {
562 DEBUG("PlanB: overlay being resumed\n");
564 st_le16 (&pb
->ch1_cmd
->command
, DBDMA_NOP
);
565 st_le16 (&pb
->ch2_cmd
->command
, DBDMA_NOP
);
566 /* Set command buffer addresses */
567 st_le32(&pb
->planb_base
->ch1
.cmdptr
,
568 virt_to_bus(pb
->overlay_last1
));
569 out_le32(&pb
->planb_base
->ch2
.cmdptr
,
570 virt_to_bus(pb
->overlay_last2
));
571 /* Start the DMA controller */
572 out_le32 (&pb
->planb_base
->ch2
.control
,
573 PLANB_CLR(PAUSE
) | PLANB_SET(RUN
|WAKE
));
574 out_le32 (&pb
->planb_base
->ch1
.control
,
575 PLANB_CLR(PAUSE
) | PLANB_SET(RUN
|WAKE
));
576 } else if(pb
->suspended
.frame
!= -1) {
577 out_le32(&pb
->planb_base
->ch1
.cmdptr
,
578 virt_to_bus(pb
->last_cmd
[pb
->suspended
.frame
]));
579 out_le32 (&pb
->planb_base
->ch1
.control
,
580 PLANB_CLR(PAUSE
) | PLANB_SET(RUN
|WAKE
));
585 wake_up_interruptible(&pb
->suspendq
);
588 static void add_clip(struct planb
*pb
, struct video_clip
*clip
)
590 volatile unsigned char *base
;
591 int xc
= clip
->x
, yc
= clip
->y
;
592 int wc
= clip
->width
, hc
= clip
->height
;
593 int ww
= pb
->win
.width
, hw
= pb
->win
.height
;
594 int x
, y
, xtmp1
, xtmp2
;
596 DEBUG("PlanB: clip %dx%d+%d+%d\n", wc
, hc
, xc
, yc
);
608 if(wc
<= 0) /* Nothing to do */
613 for (y
= yc
; y
< yc
+hc
; y
++) {
616 base
= pb
->mask
+ y
*96;
617 if(xc
!= 0 || wc
>= 8)
618 *(base
+ xtmp1
) &= (unsigned char)(0x00ff &
620 for (x
= xtmp1
+ 1; x
< xtmp2
; x
++) {
624 *(base
+ xtmp2
) &= (unsigned char)(0x00ff >>
631 static void fill_cmd_buff(struct planb
*pb
)
634 volatile struct dbdma_cmd last
;
636 DEBUG("PlanB: fill_cmd_buff()\n");
638 if(pb
->overlay_last1
!= pb
->ch1_cmd
) {
640 last
= *(pb
->overlay_last1
);
642 memset ((void *) pb
->ch1_cmd
, 0, 2 * pb
->tab_size
643 * sizeof(struct dbdma_cmd
));
646 *(pb
->overlay_last1
) = last
;
647 if(pb
->suspended
.overlay
) {
648 unsigned long jump_addr
= in_le32(&pb
->overlay_last1
->cmd_dep
);
649 if(jump_addr
!= pb
->ch1_cmd_phys
) {
652 DEBUG("PlanB: adjusting ch1's jump address\n");
654 for(i
= 0; i
< MAX_GBUFFERS
; i
++) {
655 if(pb
->need_pre_capture
[i
]) {
656 if(jump_addr
== virt_to_bus(pb
->pre_cmd
[i
]))
659 if(jump_addr
== virt_to_bus(pb
->cap_cmd
[i
]))
664 DEBUG("PlanB: not found...\n");
668 if(pb
->need_pre_capture
[i
])
669 out_le32(&pb
->pre_cmd
[i
]->phy_addr
,
670 virt_to_bus(pb
->overlay_last1
));
672 out_le32(&pb
->cap_cmd
[i
]->phy_addr
,
673 virt_to_bus(pb
->overlay_last1
));
677 pb
->cmd_buff_inited
= 1;
682 static void cmd_buff(struct planb
*pb
)
684 int i
, bpp
, count
, nlines
, stepsize
, interlace
;
685 unsigned long base
, jump
, addr_com
, addr_dep
;
686 volatile struct dbdma_cmd
*c1
= pb
->ch1_cmd
;
687 volatile struct dbdma_cmd
*c2
= pb
->ch2_cmd
;
689 interlace
= pb
->win
.interlace
;
691 count
= (bpp
* ((pb
->win
.x
+ pb
->win
.width
> pb
->win
.swidth
) ?
692 (pb
->win
.swidth
- pb
->win
.x
) : pb
->win
.width
));
693 nlines
= ((pb
->win
.y
+ pb
->win
.height
> pb
->win
.sheight
) ?
694 (pb
->win
.sheight
- pb
->win
.y
) : pb
->win
.height
);
698 /* Preamble commands: */
699 addr_com
= virt_to_bus(c1
);
700 addr_dep
= virt_to_bus(&c1
->cmd_dep
);
701 tab_cmd_dbdma(c1
++, DBDMA_NOP
, 0);
702 jump
= virt_to_bus(c1
+16); /* 14 by cmd_geo_setup() and 2 for padding */
703 if((c1
= cmd_geo_setup(c1
, pb
->win
.width
, pb
->win
.height
, interlace
,
704 bpp
, 1, pb
)) == NULL
) {
705 printk(KERN_WARNING
"PlanB: encountered serious problems\n");
706 tab_cmd_dbdma(pb
->ch1_cmd
+ 1, DBDMA_STOP
, 0);
707 tab_cmd_dbdma(pb
->ch2_cmd
+ 1, DBDMA_STOP
, 0);
710 tab_cmd_store(c1
++, addr_com
, (unsigned)(DBDMA_NOP
| BR_ALWAYS
) << 16);
711 tab_cmd_store(c1
++, addr_dep
, jump
);
712 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.wait_sel
),
713 PLANB_SET(FIELD_SYNC
));
714 /* (1) wait for field sync to be set */
715 tab_cmd_dbdma(c1
++, DBDMA_NOP
| WAIT_IFCLR
, 0);
716 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.br_sel
),
717 PLANB_SET(ODD_FIELD
));
718 /* wait for field sync to be cleared */
719 tab_cmd_dbdma(c1
++, DBDMA_NOP
| WAIT_IFSET
, 0);
720 /* if not odd field, wait until field sync is set again */
721 tab_cmd_dbdma(c1
, DBDMA_NOP
| BR_IFSET
, virt_to_bus(c1
-3)); c1
++;
722 /* assert ch_sync to ch2 */
723 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch2
.control
),
725 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.br_sel
),
726 PLANB_SET(DMA_ABORT
));
728 base
= (pb
->frame_buffer_phys
+ pb
->offset
+ pb
->win
.y
* (pb
->win
.bpl
729 + pb
->win
.pad
) + pb
->win
.x
* bpp
);
733 jump
= virt_to_bus(c1
+ (nlines
+ 1) / 2);
736 jump
= virt_to_bus(c1
+ nlines
);
739 /* even field data: */
740 for (i
=0; i
< nlines
; i
+= stepsize
, c1
++)
741 tab_cmd_gen(c1
, INPUT_MORE
| KEY_STREAM0
| BR_IFSET
,
742 count
, base
+ i
* (pb
->win
.bpl
+ pb
->win
.pad
), jump
);
744 /* For non-interlaced, we use even fields only */
746 goto cmd_tab_data_end
;
748 /* Resync to odd field */
749 /* (2) wait for field sync to be set */
750 tab_cmd_dbdma(c1
++, DBDMA_NOP
| WAIT_IFCLR
, 0);
751 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.br_sel
),
752 PLANB_SET(ODD_FIELD
));
753 /* wait for field sync to be cleared */
754 tab_cmd_dbdma(c1
++, DBDMA_NOP
| WAIT_IFSET
, 0);
755 /* if not odd field, wait until field sync is set again */
756 tab_cmd_dbdma(c1
, DBDMA_NOP
| BR_IFCLR
, virt_to_bus(c1
-3)); c1
++;
757 /* assert ch_sync to ch2 */
758 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch2
.control
),
760 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.br_sel
),
761 PLANB_SET(DMA_ABORT
));
763 /* odd field data: */
764 jump
= virt_to_bus(c1
+ nlines
/ 2);
765 for (i
=1; i
< nlines
; i
+= stepsize
, c1
++)
766 tab_cmd_gen(c1
, INPUT_MORE
| KEY_STREAM0
| BR_IFSET
, count
,
767 base
+ i
* (pb
->win
.bpl
+ pb
->win
.pad
), jump
);
769 /* And jump back to the start */
771 pb
->overlay_last1
= c1
; /* keep a pointer to the last command */
772 tab_cmd_dbdma(c1
, DBDMA_NOP
| BR_ALWAYS
, virt_to_bus(pb
->ch1_cmd
));
774 /* Clipmask command buffer */
776 /* Preamble commands: */
777 tab_cmd_dbdma(c2
++, DBDMA_NOP
, 0);
778 tab_cmd_store(c2
++, (unsigned)(&pb
->planb_base_phys
->ch2
.wait_sel
),
780 /* wait until ch1 asserts ch_sync */
781 tab_cmd_dbdma(c2
++, DBDMA_NOP
| WAIT_IFCLR
, 0);
782 /* clear ch_sync asserted by ch1 */
783 tab_cmd_store(c2
++, (unsigned)(&pb
->planb_base_phys
->ch2
.control
),
785 tab_cmd_store(c2
++, (unsigned)(&pb
->planb_base_phys
->ch2
.wait_sel
),
786 PLANB_SET(FIELD_SYNC
));
787 tab_cmd_store(c2
++, (unsigned)(&pb
->planb_base_phys
->ch2
.br_sel
),
788 PLANB_SET(ODD_FIELD
));
790 /* jump to end of even field if appropriate */
791 /* this points to (interlace)? pos. C: pos. B */
792 jump
= (interlace
) ? virt_to_bus(c2
+ (nlines
+ 1) / 2 + 2):
793 virt_to_bus(c2
+ nlines
+ 2);
794 /* if odd field, skip over to odd field clipmasking */
795 tab_cmd_dbdma(c2
++, DBDMA_NOP
| BR_IFSET
, jump
);
797 /* even field mask: */
798 tab_cmd_store(c2
++, (unsigned)(&pb
->planb_base_phys
->ch2
.br_sel
),
799 PLANB_SET(DMA_ABORT
));
800 /* this points to pos. B */
801 jump
= (interlace
) ? virt_to_bus(c2
+ nlines
+ 1):
802 virt_to_bus(c2
+ nlines
);
803 base
= virt_to_bus(pb
->mask
);
804 for (i
=0; i
< nlines
; i
+= stepsize
, c2
++)
805 tab_cmd_gen(c2
, OUTPUT_MORE
| KEY_STREAM0
| BR_IFSET
, 96,
806 base
+ i
* 96, jump
);
808 /* For non-interlaced, we use only even fields */
810 goto cmd_tab_mask_end
;
812 /* odd field mask: */
813 /* C */ tab_cmd_store(c2
++, (unsigned)(&pb
->planb_base_phys
->ch2
.br_sel
),
814 PLANB_SET(DMA_ABORT
));
815 /* this points to pos. B */
816 jump
= virt_to_bus(c2
+ nlines
/ 2);
817 base
= virt_to_bus(pb
->mask
);
818 for (i
=1; i
< nlines
; i
+= 2, c2
++) /* abort if set */
819 tab_cmd_gen(c2
, OUTPUT_MORE
| KEY_STREAM0
| BR_IFSET
, 96,
820 base
+ i
* 96, jump
);
822 /* Inform channel 1 and jump back to start */
824 /* ok, I just realized this is kind of flawed. */
825 /* this part is reached only after odd field clipmasking. */
826 /* wanna clean up? */
827 /* wait for field sync to be set */
828 /* corresponds to fsync (1) of ch1 */
829 /* B */ tab_cmd_dbdma(c2
++, DBDMA_NOP
| WAIT_IFCLR
, 0);
830 /* restart ch1, meant to clear any dead bit or something */
831 tab_cmd_store(c2
++, (unsigned)(&pb
->planb_base_phys
->ch1
.control
),
833 tab_cmd_store(c2
++, (unsigned)(&pb
->planb_base_phys
->ch1
.control
),
835 pb
->overlay_last2
= c2
; /* keep a pointer to the last command */
836 /* start over even field clipmasking */
837 tab_cmd_dbdma(c2
, DBDMA_NOP
| BR_ALWAYS
, virt_to_bus(pb
->ch2_cmd
));
843 /*********************************/
844 /* grabdisplay support functions */
845 /*********************************/
847 static int palette2fmt
[] = {
865 #define PLANB_PALETTE_MAX 15
867 static int vgrab(struct planb
*pb
, struct video_mmap
*mp
)
869 unsigned int fr
= mp
->frame
;
872 if(pb
->rawbuf
==NULL
) {
874 if((err
=grabbuf_alloc(pb
)))
878 IDEBUG("PlanB: grab %d: %dx%d(%u)\n", pb
->grabbing
,
879 mp
->width
, mp
->height
, fr
);
881 if(pb
->grabbing
>= MAX_GBUFFERS
)
883 if(fr
> (MAX_GBUFFERS
- 1) || fr
< 0)
885 if(mp
->height
<= 0 || mp
->width
<= 0)
887 if(mp
->format
< 0 || mp
->format
>= PLANB_PALETTE_MAX
)
889 if((format
= palette2fmt
[mp
->format
]) == 0)
891 if (mp
->height
* mp
->width
* format
> PLANB_MAX_FBUF
) /* format = bpp */
895 if(mp
->width
!= pb
->gwidth
[fr
] || mp
->height
!= pb
->gheight
[fr
] ||
896 format
!= pb
->gfmt
[fr
] || (pb
->gnorm_switch
[fr
])) {
898 #ifndef PLANB_GSCANLINE
899 unsigned int osize
= pb
->gwidth
[fr
] * pb
->gheight
[fr
]
901 unsigned int nsize
= mp
->width
* mp
->height
* format
;
904 IDEBUG("PlanB: gwidth = %d, gheight = %d, mp->format = %u\n",
905 mp
->width
, mp
->height
, mp
->format
);
907 #ifndef PLANB_GSCANLINE
908 if(pb
->gnorm_switch
[fr
])
911 for(i
= pb
->gbuf_idx
[fr
]; osize
> 0; i
++) {
912 memset((void *)pb
->rawbuf
[i
], 0, PAGE_SIZE
);
916 for(i
= pb
->l_fr_addr_idx
[fr
]; i
< pb
->l_fr_addr_idx
[fr
]
918 memset((void *)pb
->rawbuf
[i
], 0, PAGE_SIZE
);
922 if(pb->gnorm_switch[fr])
923 memset((void *)pb->gbuffer[fr], 0,
924 pb->gbytes_per_line * pb->gheight[fr]);
927 for(i = 0; i < pb->gheight[fr]; i++) {
928 memset((void *)(pb->gbuffer[fr]
929 + pb->gbytes_per_line * i
934 pb
->gwidth
[fr
] = mp
->width
;
935 pb
->gheight
[fr
] = mp
->height
;
936 pb
->gfmt
[fr
] = format
;
937 pb
->last_cmd
[fr
] = setup_grab_cmd(fr
, pb
);
938 planb_pre_capture(fr
, pb
->gfmt
[fr
], pb
); /* gfmt = bpp */
939 pb
->need_pre_capture
[fr
] = 1;
940 pb
->gnorm_switch
[fr
] = 0;
942 pb
->need_pre_capture
[fr
] = 0;
943 pb
->frame_stat
[fr
] = GBUFFER_GRABBING
;
944 if(!(ACTIVE
& in_le32(&pb
->planb_base
->ch1
.status
))) {
946 IDEBUG("PlanB: ch1 inactive, initiating grabbing\n");
948 planb_dbdma_stop(&pb
->planb_base
->ch1
);
949 if(pb
->need_pre_capture
[fr
]) {
951 IDEBUG("PlanB: padding pre-capture sequence\n");
953 out_le32 (&pb
->planb_base
->ch1
.cmdptr
,
954 virt_to_bus(pb
->pre_cmd
[fr
]));
956 tab_cmd_dbdma(pb
->last_cmd
[fr
], DBDMA_STOP
, 0);
957 tab_cmd_dbdma(pb
->cap_cmd
[fr
], DBDMA_NOP
, 0);
958 /* let's be on the safe side. here is not timing critical. */
959 tab_cmd_dbdma((pb
->cap_cmd
[fr
] + 1), DBDMA_NOP
, 0);
960 out_le32 (&pb
->planb_base
->ch1
.cmdptr
,
961 virt_to_bus(pb
->cap_cmd
[fr
]));
963 planb_dbdma_restart(&pb
->planb_base
->ch1
);
968 IDEBUG("PlanB: ch1 active, grabbing being queued\n");
970 if((pb
->last_fr
== -1) || ((pb
->last_fr
== -2) &&
971 overlay_is_active(pb
))) {
973 IDEBUG("PlanB: overlay is active, grabbing defered\n");
975 tab_cmd_dbdma(pb
->last_cmd
[fr
],
976 DBDMA_NOP
| BR_ALWAYS
,
977 virt_to_bus(pb
->ch1_cmd
));
978 if(pb
->need_pre_capture
[fr
]) {
980 IDEBUG("PlanB: padding pre-capture sequence\n");
982 tab_cmd_store(pb
->pre_cmd
[fr
],
983 virt_to_bus(&pb
->overlay_last1
->cmd_dep
),
984 virt_to_bus(pb
->ch1_cmd
));
986 out_le32 (&pb
->overlay_last1
->cmd_dep
,
987 virt_to_bus(pb
->pre_cmd
[fr
]));
989 tab_cmd_store(pb
->cap_cmd
[fr
],
990 virt_to_bus(&pb
->overlay_last1
->cmd_dep
),
991 virt_to_bus(pb
->ch1_cmd
));
992 tab_cmd_dbdma((pb
->cap_cmd
[fr
] + 1),
995 out_le32 (&pb
->overlay_last1
->cmd_dep
,
996 virt_to_bus(pb
->cap_cmd
[fr
]));
998 for(i
= 0; overlay_is_active(pb
) && i
< 999; i
++)
999 IDEBUG("PlanB: waiting for overlay done\n");
1000 tab_cmd_dbdma(pb
->ch1_cmd
, DBDMA_NOP
, 0);
1001 pb
->prev_last_fr
= fr
;
1003 } else if(pb
->last_fr
== -2) {
1005 IDEBUG("PlanB: mixed mode detected, grabbing"
1006 " will be done before activating overlay\n");
1008 tab_cmd_dbdma(pb
->ch1_cmd
, DBDMA_NOP
, 0);
1009 if(pb
->need_pre_capture
[fr
]) {
1011 IDEBUG("PlanB: padding pre-capture sequence\n");
1013 tab_cmd_dbdma(pb
->last_cmd
[pb
->prev_last_fr
],
1014 DBDMA_NOP
| BR_ALWAYS
,
1015 virt_to_bus(pb
->pre_cmd
[fr
]));
1018 tab_cmd_dbdma(pb
->cap_cmd
[fr
], DBDMA_NOP
, 0);
1019 if(pb
->gwidth
[pb
->prev_last_fr
] !=
1021 || pb
->gheight
[pb
->prev_last_fr
] !=
1023 || pb
->gfmt
[pb
->prev_last_fr
] !=
1025 tab_cmd_dbdma((pb
->cap_cmd
[fr
] + 1),
1028 tab_cmd_dbdma((pb
->cap_cmd
[fr
] + 1),
1029 DBDMA_NOP
| BR_ALWAYS
,
1030 virt_to_bus(pb
->cap_cmd
[fr
] + 16));
1031 tab_cmd_dbdma(pb
->last_cmd
[pb
->prev_last_fr
],
1032 DBDMA_NOP
| BR_ALWAYS
,
1033 virt_to_bus(pb
->cap_cmd
[fr
]));
1036 tab_cmd_dbdma(pb
->last_cmd
[fr
],
1037 DBDMA_NOP
| BR_ALWAYS
,
1038 virt_to_bus(pb
->ch1_cmd
));
1040 pb
->prev_last_fr
= fr
;
1044 IDEBUG("PlanB: active grabbing session detected\n");
1046 if(pb
->need_pre_capture
[fr
]) {
1048 IDEBUG("PlanB: padding pre-capture sequence\n");
1050 tab_cmd_dbdma(pb
->last_cmd
[pb
->last_fr
],
1051 DBDMA_NOP
| BR_ALWAYS
,
1052 virt_to_bus(pb
->pre_cmd
[fr
]));
1055 tab_cmd_dbdma(pb
->last_cmd
[fr
], DBDMA_STOP
, 0);
1056 tab_cmd_dbdma(pb
->cap_cmd
[fr
], DBDMA_NOP
, 0);
1057 if(pb
->gwidth
[pb
->last_fr
] != pb
->gwidth
[fr
]
1058 || pb
->gheight
[pb
->last_fr
] !=
1060 || pb
->gfmt
[pb
->last_fr
] !=
1062 tab_cmd_dbdma((pb
->cap_cmd
[fr
] + 1),
1065 tab_cmd_dbdma((pb
->cap_cmd
[fr
] + 1),
1066 DBDMA_NOP
| BR_ALWAYS
,
1067 virt_to_bus(pb
->cap_cmd
[fr
] + 16));
1068 tab_cmd_dbdma(pb
->last_cmd
[pb
->last_fr
],
1069 DBDMA_NOP
| BR_ALWAYS
,
1070 virt_to_bus(pb
->cap_cmd
[fr
]));
1075 if(!(ACTIVE
& in_le32(&pb
->planb_base
->ch1
.status
))) {
1077 IDEBUG("PlanB: became inactive in the mean time..."
1080 planb_dbdma_stop(&pb
->planb_base
->ch1
);
1081 out_le32 (&pb
->planb_base
->ch1
.cmdptr
,
1082 virt_to_bus(pb
->cap_cmd
[fr
]));
1083 planb_dbdma_restart(&pb
->planb_base
->ch1
);
1092 static void planb_pre_capture(int fr
, int bpp
, struct planb
*pb
)
1094 volatile struct dbdma_cmd
*c1
= pb
->pre_cmd
[fr
];
1095 int interlace
= (pb
->gheight
[fr
] > pb
->maxlines
/2)? 1: 0;
1097 tab_cmd_dbdma(c1
++, DBDMA_NOP
, 0);
1098 if((c1
= cmd_geo_setup(c1
, pb
->gwidth
[fr
], pb
->gheight
[fr
], interlace
,
1099 bpp
, 0, pb
)) == NULL
) {
1100 printk(KERN_WARNING
"PlanB: encountered some problems\n");
1101 tab_cmd_dbdma(pb
->pre_cmd
[fr
] + 1, DBDMA_STOP
, 0);
1104 /* Sync to even field */
1105 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.wait_sel
),
1106 PLANB_SET(FIELD_SYNC
));
1107 tab_cmd_dbdma(c1
++, DBDMA_NOP
| WAIT_IFCLR
, 0);
1108 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.br_sel
),
1109 PLANB_SET(ODD_FIELD
));
1110 tab_cmd_dbdma(c1
++, DBDMA_NOP
| WAIT_IFSET
, 0);
1111 tab_cmd_dbdma(c1
, DBDMA_NOP
| BR_IFSET
, virt_to_bus(c1
-3)); c1
++;
1112 tab_cmd_dbdma(c1
++, DBDMA_NOP
| INTR_ALWAYS
, 0);
1113 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.br_sel
),
1114 PLANB_SET(DMA_ABORT
));
1115 /* For non-interlaced, we use even fields only */
1116 if (pb
->gheight
[fr
] <= pb
->maxlines
/2)
1117 goto cmd_tab_data_end
;
1118 /* Sync to odd field */
1119 tab_cmd_dbdma(c1
++, DBDMA_NOP
| WAIT_IFCLR
, 0);
1120 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.br_sel
),
1121 PLANB_SET(ODD_FIELD
));
1122 tab_cmd_dbdma(c1
++, DBDMA_NOP
| WAIT_IFSET
, 0);
1123 tab_cmd_dbdma(c1
, DBDMA_NOP
| BR_IFCLR
, virt_to_bus(c1
-3)); c1
++;
1124 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.br_sel
),
1125 PLANB_SET(DMA_ABORT
));
1127 tab_cmd_dbdma(c1
, DBDMA_NOP
| BR_ALWAYS
, virt_to_bus(pb
->cap_cmd
[fr
]));
1132 static volatile struct dbdma_cmd
*setup_grab_cmd(int fr
, struct planb
*pb
)
1134 int i
, bpp
, count
, nlines
, stepsize
, interlace
;
1135 #ifdef PLANB_GSCANLINE
1138 int nlpp
, leftover1
;
1143 volatile struct dbdma_cmd
*c1
;
1144 volatile struct dbdma_cmd
*jump_addr
;
1146 c1
= pb
->cap_cmd
[fr
];
1147 interlace
= (pb
->gheight
[fr
] > pb
->maxlines
/2)? 1: 0;
1148 bpp
= pb
->gfmt
[fr
]; /* gfmt = bpp */
1149 count
= bpp
* pb
->gwidth
[fr
];
1150 nlines
= pb
->gheight
[fr
];
1151 #ifdef PLANB_GSCANLINE
1152 scanline
= pb
->gbytes_per_line
;
1154 pb
->lsize
[fr
] = count
;
1160 /* Preamble commands: */
1161 tab_cmd_dbdma(c1
++, DBDMA_NOP
, 0);
1162 tab_cmd_dbdma(c1
, DBDMA_NOP
| BR_ALWAYS
, virt_to_bus(c1
+ 16)); c1
++;
1163 if((c1
= cmd_geo_setup(c1
, pb
->gwidth
[fr
], pb
->gheight
[fr
], interlace
,
1164 bpp
, 0, pb
)) == NULL
) {
1165 printk(KERN_WARNING
"PlanB: encountered serious problems\n");
1166 tab_cmd_dbdma(pb
->cap_cmd
[fr
] + 1, DBDMA_STOP
, 0);
1167 return (pb
->cap_cmd
[fr
] + 2);
1169 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.wait_sel
),
1170 PLANB_SET(FIELD_SYNC
));
1171 tab_cmd_dbdma(c1
++, DBDMA_NOP
| WAIT_IFCLR
, 0);
1172 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.br_sel
),
1173 PLANB_SET(ODD_FIELD
));
1174 tab_cmd_dbdma(c1
++, DBDMA_NOP
| WAIT_IFSET
, 0);
1175 tab_cmd_dbdma(c1
, DBDMA_NOP
| BR_IFSET
, virt_to_bus(c1
-3)); c1
++;
1176 tab_cmd_dbdma(c1
++, DBDMA_NOP
| INTR_ALWAYS
, 0);
1177 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.br_sel
),
1178 PLANB_SET(DMA_ABORT
));
1182 jump_addr
= c1
+ TAB_FACTOR
* (nlines
+ 1) / 2;
1185 jump_addr
= c1
+ TAB_FACTOR
* nlines
;
1187 jump
= virt_to_bus(jump_addr
);
1189 /* even field data: */
1191 pagei
= pb
->gbuf_idx
[fr
];
1192 #ifdef PLANB_GSCANLINE
1193 for (i
= 0; i
< nlines
; i
+= stepsize
) {
1194 tab_cmd_gen(c1
++, INPUT_MORE
| BR_IFSET
, count
,
1195 virt_to_bus(pb
->rawbuf
[pagei
1196 + i
* scanline
/ PAGE_SIZE
]), jump
);
1204 base
= virt_to_bus(pb
->rawbuf
[pagei
]);
1205 nlpp
= (PAGE_SIZE
- leftover1
) / count
/ stepsize
;
1206 for(j
= 0; j
< nlpp
&& i
< nlines
; j
++, i
+= stepsize
, c1
++)
1207 tab_cmd_gen(c1
, INPUT_MORE
| KEY_STREAM0
| BR_IFSET
,
1208 count
, base
+ count
* j
* stepsize
+ leftover1
, jump
);
1210 int lov0
= PAGE_SIZE
- count
* nlpp
* stepsize
- leftover1
;
1216 tab_cmd_gen(c1
++, INPUT_MORE
| BR_IFSET
, count
, base
1217 + count
* nlpp
* stepsize
+ leftover1
, jump
);
1219 pb
->l_to_addr
[fr
][pb
->lnum
[fr
]] = pb
->rawbuf
[pagei
]
1220 + count
* nlpp
* stepsize
+ leftover1
;
1221 pb
->l_to_next_idx
[fr
][pb
->lnum
[fr
]] = pagei
+ 1;
1222 pb
->l_to_next_size
[fr
][pb
->lnum
[fr
]] = count
- lov0
;
1223 tab_cmd_gen(c1
++, INPUT_MORE
| BR_IFSET
, count
,
1224 virt_to_bus(pb
->rawbuf
[pb
->l_fr_addr_idx
[fr
]
1225 + pb
->lnum
[fr
]]), jump
);
1226 if(++pb
->lnum
[fr
] > MAX_LNUM
)
1229 leftover1
= count
* stepsize
- lov0
;
1234 } while(i
< nlines
);
1235 tab_cmd_dbdma(c1
, DBDMA_NOP
| BR_ALWAYS
, jump
);
1237 #endif /* PLANB_GSCANLINE */
1239 /* For non-interlaced, we use even fields only */
1241 goto cmd_tab_data_end
;
1243 /* Sync to odd field */
1244 tab_cmd_dbdma(c1
++, DBDMA_NOP
| WAIT_IFCLR
, 0);
1245 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.br_sel
),
1246 PLANB_SET(ODD_FIELD
));
1247 tab_cmd_dbdma(c1
++, DBDMA_NOP
| WAIT_IFSET
, 0);
1248 tab_cmd_dbdma(c1
, DBDMA_NOP
| BR_IFCLR
, virt_to_bus(c1
-3)); c1
++;
1249 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->ch1
.br_sel
),
1250 PLANB_SET(DMA_ABORT
));
1252 /* odd field data: */
1253 jump_addr
= c1
+ TAB_FACTOR
* nlines
/ 2;
1254 jump
= virt_to_bus(jump_addr
);
1255 #ifdef PLANB_GSCANLINE
1256 for (i
= 1; i
< nlines
; i
+= stepsize
) {
1257 tab_cmd_gen(c1
++, INPUT_MORE
| BR_IFSET
, count
,
1258 virt_to_bus(pb
->rawbuf
[pagei
1259 + i
* scanline
/ PAGE_SIZE
]), jump
);
1264 pagei
= pb
->gbuf_idx
[fr
];
1270 base
= virt_to_bus(pb
->rawbuf
[pagei
]);
1271 nlpp
= (PAGE_SIZE
- leftover1
) / count
/ stepsize
;
1272 if(leftover1
>= count
) {
1273 tab_cmd_gen(c1
++, INPUT_MORE
| KEY_STREAM0
| BR_IFSET
, count
,
1274 base
+ leftover1
- count
, jump
);
1277 for(j
= 0; j
< nlpp
&& i
< nlines
; j
++, i
+= stepsize
, c1
++)
1278 tab_cmd_gen(c1
, INPUT_MORE
| KEY_STREAM0
| BR_IFSET
, count
,
1279 base
+ count
* (j
* stepsize
+ 1) + leftover1
, jump
);
1281 int lov0
= PAGE_SIZE
- count
* nlpp
* stepsize
- leftover1
;
1287 pb
->l_to_addr
[fr
][pb
->lnum
[fr
]] = pb
->rawbuf
[pagei
]
1288 + count
* (nlpp
* stepsize
+ 1) + leftover1
;
1289 pb
->l_to_next_idx
[fr
][pb
->lnum
[fr
]] = pagei
+ 1;
1290 pb
->l_to_next_size
[fr
][pb
->lnum
[fr
]] = count
* stepsize
1292 tab_cmd_gen(c1
++, INPUT_MORE
| BR_IFSET
, count
,
1293 virt_to_bus(pb
->rawbuf
[pb
->l_fr_addr_idx
[fr
]
1294 + pb
->lnum
[fr
]]), jump
);
1295 if(++pb
->lnum
[fr
] > MAX_LNUM
)
1299 leftover1
= count
* stepsize
- lov0
;
1303 } while(i
< nlines
);
1305 tab_cmd_dbdma(c1
, DBDMA_NOP
| BR_ALWAYS
, jump
);
1307 #endif /* PLANB_GSCANLINE */
1310 tab_cmd_store(c1
++, (unsigned)(&pb
->planb_base_phys
->intr_stat
),
1311 (fr
<< 9) | PLANB_FRM_IRQ
| PLANB_GEN_IRQ
);
1313 tab_cmd_dbdma(c1
, DBDMA_STOP
, 0);
1319 static void planb_irq(int irq
, void *dev_id
)
1321 unsigned int stat
, astat
;
1322 struct planb
*pb
= (struct planb
*)dev_id
;
1324 IDEBUG("PlanB: planb_irq()\n");
1326 /* get/clear interrupt status bits */
1328 stat
= in_le32(&pb
->planb_base
->intr_stat
);
1329 astat
= stat
& pb
->intr_mask
;
1330 out_le32(&pb
->planb_base
->intr_stat
, PLANB_FRM_IRQ
1331 & ~astat
& stat
& ~PLANB_GEN_IRQ
);
1332 IDEBUG("PlanB: stat = %X, astat = %X\n", stat
, astat
);
1334 if(astat
& PLANB_FRM_IRQ
) {
1335 unsigned int fr
= stat
>> 9;
1336 #ifndef PLANB_GSCANLINE
1339 IDEBUG("PlanB: PLANB_FRM_IRQ\n");
1343 IDEBUG("PlanB: grab %d: fr = %d, gcount = %d\n",
1344 pb
->grabbing
, fr
, pb
->gcount
);
1345 #ifndef PLANB_GSCANLINE
1346 IDEBUG("PlanB: %d * %d bytes are being copied over\n",
1347 pb
->lnum
[fr
], pb
->lsize
[fr
]);
1348 for(i
= 0; i
< pb
->lnum
[fr
]; i
++) {
1349 int first
= pb
->lsize
[fr
] - pb
->l_to_next_size
[fr
][i
];
1351 memcpy(pb
->l_to_addr
[fr
][i
],
1352 pb
->rawbuf
[pb
->l_fr_addr_idx
[fr
] + i
],
1354 memcpy(pb
->rawbuf
[pb
->l_to_next_idx
[fr
][i
]],
1355 pb
->rawbuf
[pb
->l_fr_addr_idx
[fr
] + i
] + first
,
1356 pb
->l_to_next_size
[fr
][i
]);
1359 pb
->frame_stat
[fr
] = GBUFFER_DONE
;
1361 wake_up_interruptible(&pb
->capq
);
1364 /* incorrect interrupts? */
1365 pb
->intr_mask
= PLANB_CLR_IRQ
;
1366 out_le32(&pb
->planb_base
->intr_stat
, PLANB_CLR_IRQ
);
1367 printk(KERN_ERR
"PlanB: IRQ lockup, cleared intrrupts"
1368 " unconditionally\n");
1371 /*******************************
1372 * Device Operations functions *
1373 *******************************/
1375 static int planb_open(struct video_device
*dev
, int mode
)
1377 struct planb
*pb
= (struct planb
*)dev
;
1379 if (pb
->user
== 0) {
1381 if((err
= planb_prepare_open(pb
)) != 0)
1386 DEBUG("PlanB: device opened\n");
1390 static void planb_close(struct video_device
*dev
)
1392 struct planb
*pb
= (struct planb
*)dev
;
1394 if(pb
->user
< 1) /* ??? */
1397 if (pb
->user
== 1) {
1399 planb_dbdma_stop(&pb
->planb_base
->ch2
);
1400 planb_dbdma_stop(&pb
->planb_base
->ch1
);
1403 planb_prepare_close(pb
);
1408 DEBUG("PlanB: device closed\n");
1411 static long planb_read(struct video_device
*v
, char *buf
, unsigned long count
,
1414 DEBUG("planb: read request\n");
1418 static long planb_write(struct video_device
*v
, const char *buf
,
1419 unsigned long count
, int nonblock
)
1421 DEBUG("planb: write request\n");
1425 static int planb_ioctl(struct video_device
*dev
, unsigned int cmd
, void *arg
)
1427 struct planb
*pb
=(struct planb
*)dev
;
1433 struct video_capability b
;
1435 DEBUG("PlanB: IOCTL VIDIOCGCAP\n");
1437 strcpy (b
.name
, pb
->video_dev
.name
);
1438 b
.type
= VID_TYPE_OVERLAY
| VID_TYPE_CLIPPING
|
1439 VID_TYPE_FRAMERAM
| VID_TYPE_SCALES
|
1441 b
.channels
= 2; /* composite & svhs */
1443 b
.maxwidth
= PLANB_MAXPIXELS
;
1444 b
.maxheight
= PLANB_MAXLINES
;
1445 b
.minwidth
= 32; /* wild guess */
1447 if (copy_to_user(arg
,&b
,sizeof(b
)))
1453 struct video_buffer v
;
1457 DEBUG("PlanB: IOCTL VIDIOCSFBUF\n");
1459 if (!capable(CAP_SYS_ADMIN
)
1460 || !capable(CAP_SYS_RAWIO
))
1462 if (copy_from_user(&v
, arg
,sizeof(v
)))
1473 fmt
= PLANB_COLOUR15
;
1478 fmt
= PLANB_COLOUR32
;
1484 if (bpp
* v
.width
> v
.bytesperline
) {
1489 pb
->win
.color_fmt
= fmt
;
1490 pb
->frame_buffer_phys
= (unsigned long) v
.base
;
1491 pb
->win
.sheight
= v
.height
;
1492 pb
->win
.swidth
= v
.width
;
1493 pb
->picture
.depth
= pb
->win
.depth
= v
.depth
;
1494 pb
->win
.bpl
= pb
->win
.bpp
* pb
->win
.swidth
;
1495 pb
->win
.pad
= v
.bytesperline
- pb
->win
.bpl
;
1497 DEBUG("PlanB: Display at %p is %d by %d, bytedepth %d,"
1498 " bpl %d (+ %d)\n", v
.base
, v
.width
,v
.height
,
1499 pb
->win
.bpp
, pb
->win
.bpl
, pb
->win
.pad
);
1501 pb
->cmd_buff_inited
= 0;
1503 suspend_overlay(pb
);
1512 struct video_buffer v
;
1514 DEBUG("PlanB: IOCTL VIDIOCGFBUF\n");
1516 v
.base
= (void *)pb
->frame_buffer_phys
;
1517 v
.height
= pb
->win
.sheight
;
1518 v
.width
= pb
->win
.swidth
;
1519 v
.depth
= pb
->win
.depth
;
1520 v
.bytesperline
= pb
->win
.bpl
+ pb
->win
.pad
;
1521 if (copy_to_user(arg
, &v
, sizeof(v
)))
1529 if(copy_from_user(&i
, arg
, sizeof(i
)))
1532 DEBUG("PlanB: IOCTL VIDIOCCAPTURE Stop\n");
1541 DEBUG("PlanB: IOCTL VIDIOCCAPTURE Start\n");
1543 if (pb
->frame_buffer_phys
== 0 ||
1544 pb
->win
.width
== 0 ||
1545 pb
->win
.height
== 0)
1551 if(!(pb
->cmd_buff_inited
))
1560 struct video_channel v
;
1562 DEBUG("PlanB: IOCTL VIDIOCGCHAN\n");
1564 if(copy_from_user(&v
, arg
,sizeof(v
)))
1568 v
.type
= VIDEO_TYPE_CAMERA
;
1569 v
.norm
= pb
->win
.norm
;
1573 strcpy(v
.name
,"Composite");
1576 strcpy(v
.name
,"SVHS");
1582 if(copy_to_user(arg
,&v
,sizeof(v
)))
1589 struct video_channel v
;
1591 DEBUG("PlanB: IOCTL VIDIOCSCHAN\n");
1593 if(copy_from_user(&v
, arg
, sizeof(v
)))
1596 if (v
.norm
!= pb
->win
.norm
) {
1601 case VIDEO_MODE_PAL
:
1602 case VIDEO_MODE_SECAM
:
1603 maxlines
= PLANB_MAXLINES
;
1605 case VIDEO_MODE_NTSC
:
1606 maxlines
= PLANB_NTSC_MAXLINES
;
1613 /* empty the grabbing queue */
1614 wait_event(pb
->capq
, !pb
->grabbing
);
1615 pb
->maxlines
= maxlines
;
1616 pb
->win
.norm
= v
.norm
;
1617 /* Stop overlay if running */
1618 suspend_overlay(pb
);
1619 for(i
= 0; i
< MAX_GBUFFERS
; i
++)
1620 pb
->gnorm_switch
[i
] = 1;
1621 /* I know it's an overkill, but.... */
1623 /* ok, now init it accordingly */
1625 /* restart overlay if it was running */
1632 case 0: /* Composite */
1633 saa_set (SAA7196_IOCC
,
1634 ((saa_regs
[pb
->win
.norm
][SAA7196_IOCC
] &
1638 saa_set (SAA7196_IOCC
,
1639 ((saa_regs
[pb
->win
.norm
][SAA7196_IOCC
] &
1651 struct video_picture vp
= pb
->picture
;
1653 DEBUG("PlanB: IOCTL VIDIOCGPICT\n");
1655 switch(pb
->win
.color_fmt
) {
1657 vp
.palette
= VIDEO_PALETTE_GREY
;
1658 case PLANB_COLOUR15
:
1659 vp
.palette
= VIDEO_PALETTE_RGB555
;
1661 case PLANB_COLOUR32
:
1662 vp
.palette
= VIDEO_PALETTE_RGB32
;
1669 if(copy_to_user(arg
,&vp
,sizeof(vp
)))
1675 struct video_picture vp
;
1677 DEBUG("PlanB: IOCTL VIDIOCSPICT\n");
1679 if(copy_from_user(&vp
,arg
,sizeof(vp
)))
1682 /* Should we do sanity checks here? */
1683 saa_set (SAA7196_BRIG
, (unsigned char)
1684 ((pb
->picture
.brightness
) >> 8), pb
);
1685 saa_set (SAA7196_HUEC
, (unsigned char)
1686 ((pb
->picture
.hue
) >> 8) ^ 0x80, pb
);
1687 saa_set (SAA7196_CSAT
, (unsigned char)
1688 ((pb
->picture
.colour
) >> 9), pb
);
1689 saa_set (SAA7196_CONT
, (unsigned char)
1690 ((pb
->picture
.contrast
) >> 9), pb
);
1696 struct video_window vw
;
1697 struct video_clip clip
;
1700 DEBUG("PlanB: IOCTL VIDIOCSWIN\n");
1702 if(copy_from_user(&vw
,arg
,sizeof(vw
)))
1706 /* Stop overlay if running */
1707 suspend_overlay(pb
);
1708 pb
->win
.interlace
= (vw
.height
> pb
->maxlines
/2)? 1: 0;
1709 if (pb
->win
.x
!= vw
.x
||
1710 pb
->win
.y
!= vw
.y
||
1711 pb
->win
.width
!= vw
.width
||
1712 pb
->win
.height
!= vw
.height
||
1713 !pb
->cmd_buff_inited
) {
1716 pb
->win
.width
= vw
.width
;
1717 pb
->win
.height
= vw
.height
;
1720 /* Reset clip mask */
1721 memset ((void *) pb
->mask
, 0xff, (pb
->maxlines
1722 * ((PLANB_MAXPIXELS
+ 7) & ~7)) / 8);
1723 /* Add any clip rects */
1724 for (i
= 0; i
< vw
.clipcount
; i
++) {
1725 if (copy_from_user(&clip
, vw
.clips
+ i
,
1726 sizeof(struct video_clip
)))
1728 add_clip(pb
, &clip
);
1730 /* restart overlay if it was running */
1737 struct video_window vw
;
1739 DEBUG("PlanB: IOCTL VIDIOCGWIN\n");
1743 vw
.width
=pb
->win
.width
;
1744 vw
.height
=pb
->win
.height
;
1747 if(pb
->win
.interlace
)
1748 vw
.flags
|=VIDEO_WINDOW_INTERLACE
;
1749 if(copy_to_user(arg
,&vw
,sizeof(vw
)))
1756 IDEBUG("PlanB: IOCTL VIDIOCSYNC\n");
1758 if(copy_from_user((void *)&i
,arg
,sizeof(int)))
1761 IDEBUG("PlanB: sync to frame %d\n", i
);
1763 if(i
> (MAX_GBUFFERS
- 1) || i
< 0)
1766 switch (pb
->frame_stat
[i
]) {
1767 case GBUFFER_UNUSED
:
1769 case GBUFFER_GRABBING
:
1770 IDEBUG("PlanB: waiting for grab"
1772 interruptible_sleep_on(&pb
->capq
);
1773 if(signal_pending(current
))
1777 pb
->frame_stat
[i
] = GBUFFER_UNUSED
;
1783 case VIDIOCMCAPTURE
:
1785 struct video_mmap vm
;
1786 volatile unsigned int status
;
1788 IDEBUG("PlanB: IOCTL VIDIOCMCAPTURE\n");
1790 if(copy_from_user((void *) &vm
,(void *)arg
,sizeof(vm
)))
1792 status
= pb
->frame_stat
[vm
.frame
];
1793 if (status
!= GBUFFER_UNUSED
)
1796 return vgrab(pb
, &vm
);
1802 struct video_mbuf vm
;
1804 DEBUG("PlanB: IOCTL VIDIOCGMBUF\n");
1806 memset(&vm
, 0 , sizeof(vm
));
1807 vm
.size
= PLANB_MAX_FBUF
* MAX_GBUFFERS
;
1808 vm
.frames
= MAX_GBUFFERS
;
1809 for(i
= 0; i
<MAX_GBUFFERS
; i
++)
1810 vm
.offsets
[i
] = PLANB_MAX_FBUF
* i
;
1811 if(copy_to_user((void *)arg
, (void *)&vm
, sizeof(vm
)))
1816 case PLANBIOCGSAAREGS
:
1818 struct planb_saa_regs preg
;
1820 DEBUG("PlanB: IOCTL PLANBIOCGSAAREGS\n");
1822 if(copy_from_user(&preg
, arg
, sizeof(preg
)))
1824 if(preg
.addr
>= SAA7196_NUMREGS
)
1826 preg
.val
= saa_regs
[pb
->win
.norm
][preg
.addr
];
1827 if(copy_to_user((void *)arg
, (void *)&preg
,
1833 case PLANBIOCSSAAREGS
:
1835 struct planb_saa_regs preg
;
1837 DEBUG("PlanB: IOCTL PLANBIOCSSAAREGS\n");
1839 if(copy_from_user(&preg
, arg
, sizeof(preg
)))
1841 if(preg
.addr
>= SAA7196_NUMREGS
)
1843 saa_set (preg
.addr
, preg
.val
, pb
);
1849 struct planb_stat_regs pstat
;
1851 DEBUG("PlanB: IOCTL PLANBIOCGSTAT\n");
1853 pstat
.ch1_stat
= in_le32(&pb
->planb_base
->ch1
.status
);
1854 pstat
.ch2_stat
= in_le32(&pb
->planb_base
->ch2
.status
);
1855 pstat
.saa_stat0
= saa_status(0, pb
);
1856 pstat
.saa_stat1
= saa_status(1, pb
);
1858 if(copy_to_user((void *)arg
, (void *)&pstat
,
1864 case PLANBIOCSMODE
: {
1867 DEBUG("PlanB: IOCTL PLANBIOCSMODE\n");
1869 if(copy_from_user(&v
, arg
, sizeof(v
)))
1875 saa_set (SAA7196_STDC
,
1876 (saa_regs
[pb
->win
.norm
][SAA7196_STDC
] &
1879 case PLANB_VTR_MODE
:
1880 saa_set (SAA7196_STDC
,
1881 (saa_regs
[pb
->win
.norm
][SAA7196_STDC
] |
1891 case PLANBIOCGMODE
: {
1894 DEBUG("PlanB: IOCTL PLANBIOCGMODE\n");
1896 if(copy_to_user(arg
,&v
,sizeof(v
)))
1900 #ifdef PLANB_GSCANLINE
1901 case PLANBG_GRAB_BPL
: {
1902 int v
=pb
->gbytes_per_line
;
1904 DEBUG("PlanB: IOCTL PLANBG_GRAB_BPL\n");
1906 if(copy_to_user(arg
,&v
,sizeof(v
)))
1910 #endif /* PLANB_GSCANLINE */
1911 case PLANB_INTR_DEBUG
: {
1914 DEBUG("PlanB: IOCTL PLANB_INTR_DEBUG\n");
1916 if(copy_from_user(&i
, arg
, sizeof(i
)))
1919 /* avoid hang ups all together */
1920 for (i
= 0; i
< MAX_GBUFFERS
; i
++) {
1921 if(pb
->frame_stat
[i
] == GBUFFER_GRABBING
) {
1922 pb
->frame_stat
[i
] = GBUFFER_DONE
;
1927 wake_up_interruptible(&pb
->capq
);
1930 case PLANB_INV_REGS
: {
1932 struct planb_any_regs any
;
1934 DEBUG("PlanB: IOCTL PLANB_INV_REGS\n");
1936 if(copy_from_user(&any
, arg
, sizeof(any
)))
1938 if(any
.offset
< 0 || any
.offset
+ any
.bytes
> 0x400)
1942 for (i
= 0; i
< any
.bytes
; i
++) {
1944 in_8((unsigned char *)pb
->planb_base
1947 if(copy_to_user(arg
,&any
,sizeof(any
)))
1953 DEBUG("PlanB: Unimplemented IOCTL\n");
1954 return -ENOIOCTLCMD
;
1956 /* Some IOCTLs are currently unsupported on PlanB */
1957 case VIDIOCGTUNER
: {
1958 DEBUG("PlanB: IOCTL VIDIOCGTUNER\n");
1959 goto unimplemented
; }
1960 case VIDIOCSTUNER
: {
1961 DEBUG("PlanB: IOCTL VIDIOCSTUNER\n");
1962 goto unimplemented
; }
1964 DEBUG("PlanB: IOCTL VIDIOCSFREQ\n");
1965 goto unimplemented
; }
1967 DEBUG("PlanB: IOCTL VIDIOCGFREQ\n");
1968 goto unimplemented
; }
1970 DEBUG("PlanB: IOCTL VIDIOCKEY\n");
1971 goto unimplemented
; }
1972 case VIDIOCSAUDIO
: {
1973 DEBUG("PlanB: IOCTL VIDIOCSAUDIO\n");
1974 goto unimplemented
; }
1975 case VIDIOCGAUDIO
: {
1976 DEBUG("PlanB: IOCTL VIDIOCGAUDIO\n");
1977 goto unimplemented
; }
1979 DEBUG(" Unimplemented\n");
1980 return -ENOIOCTLCMD
;
1985 static int planb_mmap(struct vm_area_struct
*vma
, struct video_device
*dev
, const char *adr
, unsigned long size
)
1988 struct planb
*pb
= (struct planb
*)dev
;
1989 unsigned long start
= (unsigned long)adr
;
1991 if (size
> MAX_GBUFFERS
* PLANB_MAX_FBUF
)
1995 if((err
=grabbuf_alloc(pb
)))
1998 for (i
= 0; i
< pb
->rawbuf_size
; i
++) {
2001 pfn
= virt_to_phys((void *)pb
->rawbuf
[i
]) >> PAGE_SHIFT
;
2002 if (remap_pfn_range(vma
, start
, pfn
, PAGE_SIZE
, PAGE_SHARED
))
2005 if (size
<= PAGE_SIZE
)
2012 static struct video_device planb_template
=
2014 .owner
= THIS_MODULE
,
2015 .name
= PLANB_DEVICE_NAME
,
2016 .type
= VID_TYPE_OVERLAY
,
2017 .hardware
= VID_HARDWARE_PLANB
,
2019 .close
= planb_close
,
2021 .write
= planb_write
,
2022 .ioctl
= planb_ioctl
,
2023 .mmap
= planb_mmap
, /* mmap? */
2026 static int init_planb(struct planb
*pb
)
2028 unsigned char saa_rev
;
2031 memset ((void *) &pb
->win
, 0, sizeof (struct planb_window
));
2032 /* Simple sanity check */
2033 if(def_norm
>= NUM_SUPPORTED_NORM
|| def_norm
< 0) {
2034 printk(KERN_ERR
"PlanB: Option(s) invalid\n");
2037 pb
->win
.norm
= def_norm
;
2038 pb
->win
.mode
= PLANB_TV_MODE
; /* TV mode */
2039 pb
->win
.interlace
=1;
2042 pb
->win
.width
=768; /* 640 */
2043 pb
->win
.height
=576; /* 480 */
2046 btv
->win
.cropwidth
=768; /* 640 */
2047 btv
->win
.cropheight
=576; /* 480 */
2054 pb
->win
.color_fmt
=PLANB_COLOUR32
;
2055 pb
->win
.bpl
=1024*pb
->win
.bpp
;
2056 pb
->win
.swidth
=1024;
2057 pb
->win
.sheight
=768;
2058 #ifdef PLANB_GSCANLINE
2059 if((pb
->gbytes_per_line
= PLANB_MAXPIXELS
* 4) > PAGE_SIZE
2060 || (pb
->gbytes_per_line
<= 0))
2063 /* page align pb->gbytes_per_line for DMA purpose */
2064 for(i
= PAGE_SIZE
; pb
->gbytes_per_line
< (i
>>1);)
2066 pb
->gbytes_per_line
= i
;
2069 pb
->tab_size
= PLANB_MAXLINES
+ 40;
2071 mutex_init(&pb
->lock
);
2079 init_waitqueue_head(&pb
->suspendq
);
2080 pb
->cmd_buff_inited
= 0;
2081 pb
->frame_buffer_phys
= 0;
2083 /* Reset DMA controllers */
2084 planb_dbdma_stop(&pb
->planb_base
->ch2
);
2085 planb_dbdma_stop(&pb
->planb_base
->ch1
);
2087 saa_rev
= (saa_status(0, pb
) & 0xf0) >> 4;
2088 printk(KERN_INFO
"PlanB: SAA7196 video processor rev. %d\n", saa_rev
);
2089 /* Initialize the SAA registers in memory and on chip */
2092 /* clear interrupt mask */
2093 pb
->intr_mask
= PLANB_CLR_IRQ
;
2095 result
= request_irq(pb
->irq
, planb_irq
, 0, "PlanB", (void *)pb
);
2097 if (result
==-EINVAL
)
2098 printk(KERN_ERR
"PlanB: Bad irq number (%d) "
2099 "or handler\n", (int)pb
->irq
);
2100 else if (result
==-EBUSY
)
2101 printk(KERN_ERR
"PlanB: I don't know why, "
2102 "but IRQ %d is busy\n", (int)pb
->irq
);
2105 disable_irq(pb
->irq
);
2107 /* Now add the template and register the device unit. */
2108 memcpy(&pb
->video_dev
,&planb_template
,sizeof(planb_template
));
2110 pb
->picture
.brightness
=0x90<<8;
2111 pb
->picture
.contrast
= 0x70 << 8;
2112 pb
->picture
.colour
= 0x70<<8;
2113 pb
->picture
.hue
= 0x8000;
2114 pb
->picture
.whiteness
= 0;
2115 pb
->picture
.depth
= pb
->win
.depth
;
2117 pb
->frame_stat
=NULL
;
2118 init_waitqueue_head(&pb
->capq
);
2119 for(i
=0; i
<MAX_GBUFFERS
; i
++) {
2120 pb
->gbuf_idx
[i
] = PLANB_MAX_FBUF
* i
/ PAGE_SIZE
;
2124 pb
->cap_cmd
[i
]=NULL
;
2125 #ifndef PLANB_GSCANLINE
2126 pb
->l_fr_addr_idx
[i
] = MAX_GBUFFERS
* (PLANB_MAX_FBUF
2127 / PAGE_SIZE
+ 1) + MAX_LNUM
* i
;
2135 /* enable interrupts */
2136 out_le32(&pb
->planb_base
->intr_stat
, PLANB_CLR_IRQ
);
2137 pb
->intr_mask
= PLANB_FRM_IRQ
;
2138 enable_irq(pb
->irq
);
2140 if(video_register_device(&pb
->video_dev
, VFL_TYPE_GRABBER
, video_nr
)<0)
2147 * Scan for a PlanB controller, request the irq and map the io memory
2150 static int find_planb(void)
2153 struct device_node
*planb_devices
;
2154 unsigned char dev_fn
, confreg
, bus
;
2155 unsigned int old_base
, new_base
;
2157 struct pci_dev
*pdev
;
2160 if (!machine_is(powermac
))
2163 planb_devices
= of_find_node_by_name(NULL
, "planb");
2164 if (planb_devices
== 0) {
2166 printk(KERN_WARNING
"PlanB: no device found!\n");
2170 if (planb_devices
->next
!= NULL
)
2171 printk(KERN_ERR
"Warning: only using first PlanB device!\n");
2175 if (planb_devices
->n_addrs
!= 1) {
2176 printk (KERN_WARNING
"PlanB: expecting 1 address for planb "
2177 "(got %d)", planb_devices
->n_addrs
);
2178 of_node_put(planb_devices
);
2182 if (planb_devices
->n_intrs
== 0) {
2183 printk(KERN_WARNING
"PlanB: no intrs for device %s\n",
2184 planb_devices
->full_name
);
2185 of_node_put(planb_devices
);
2188 irq
= planb_devices
->intrs
[0].line
;
2191 /* Initialize PlanB's PCI registers */
2193 /* There is a bug with the way OF assigns addresses
2194 to the devices behind the chaos bridge.
2195 control needs only 0x1000 of space, but decodes only
2196 the upper 16 bits. It therefore occupies a full 64K.
2197 OF assigns the planb controller memory within this space;
2198 so we need to change that here in order to access planb. */
2200 /* We remap to 0xf1000000 in hope that nobody uses it ! */
2202 bus
= (planb_devices
->addrs
[0].space
>> 16) & 0xff;
2203 dev_fn
= (planb_devices
->addrs
[0].space
>> 8) & 0xff;
2204 confreg
= planb_devices
->addrs
[0].space
& 0xff;
2205 old_base
= planb_devices
->addrs
[0].address
;
2206 new_base
= 0xf1000000;
2207 of_node_put(planb_devices
);
2209 DEBUG("PlanB: Found on bus %d, dev %d, func %d, "
2210 "membase 0x%x (base reg. 0x%x)\n",
2211 bus
, PCI_SLOT(dev_fn
), PCI_FUNC(dev_fn
), old_base
, confreg
);
2213 pdev
= pci_get_bus_and_slot(bus
, dev_fn
);
2215 printk(KERN_ERR
"planb: cannot find slot\n");
2219 /* Enable response in memory space, bus mastering,
2220 use memory write and invalidate */
2221 rc
= pci_enable_device(pdev
);
2223 printk(KERN_ERR
"planb: cannot enable PCI device %s\n",
2227 rc
= pci_set_mwi(pdev
);
2229 printk(KERN_ERR
"planb: cannot enable MWI on PCI device %s\n",
2231 goto err_out_disable
;
2233 pci_set_master(pdev
);
2235 /* Set the new base address */
2236 pci_write_config_dword (pdev
, confreg
, new_base
);
2238 planb_regs
= (volatile struct planb_registers
*)
2239 ioremap (new_base
, 0x400);
2240 pb
->planb_base
= planb_regs
;
2241 pb
->planb_base_phys
= (struct planb_registers
*)new_base
;
2248 pci_disable_device(pdev
);
2250 /* FIXME handle error */ /* comment moved from pci_find_slot, above */
2255 static void release_planb(void)
2260 for (i
=0;i
<planb_num
; i
++)
2264 /* stop and flash DMAs unconditionally */
2265 planb_dbdma_stop(&pb
->planb_base
->ch2
);
2266 planb_dbdma_stop(&pb
->planb_base
->ch1
);
2268 /* clear and free interrupts */
2269 pb
->intr_mask
= PLANB_CLR_IRQ
;
2270 out_le32 (&pb
->planb_base
->intr_stat
, PLANB_CLR_IRQ
);
2271 free_irq(pb
->irq
, pb
);
2273 /* make sure all allocated memory are freed */
2274 planb_prepare_close(pb
);
2276 printk(KERN_INFO
"PlanB: unregistering with v4l\n");
2277 video_unregister_device(&pb
->video_dev
);
2279 pci_dev_put(pb
->dev
);
2281 /* note that iounmap() does nothing on the PPC right now */
2282 iounmap ((void *)pb
->planb_base
);
2286 static int __init
init_planbs(void)
2290 if (find_planb()<=0)
2293 for (i
=0; i
<planb_num
; i
++) {
2294 if (init_planb(&planbs
[i
])<0) {
2295 printk(KERN_ERR
"PlanB: error registering device %d"
2300 printk(KERN_INFO
"PlanB: registered device %d with v4l\n", i
);
2305 static void __exit
exit_planbs(void)
2310 module_init(init_planbs
);
2311 module_exit(exit_planbs
);