2 planb - v4l-compatible frame grabber driver for the PlanB hardware
4 PlanB is used in the 7x00/8x00 series of PowerMacintosh
5 Computers as video input DMA controller.
7 Copyright (C) 1998 - 2002 Michel Lanners <mailto:mlan@cpu.lu>
9 Based largely on the old bttv driver by Ralph Metzler
11 Additional debugging and coding by Takashi Oe <mailto:toe@unlserve.unl.edu>
13 For more information, see <http://www.cpu.lu/~mlan/planb.html>
16 This program is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation; either version 2 of the License, or
19 (at your option) any later version.
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 /* $Id: planb.c,v 2.11 2002/04/03 15:57:57 mlan Exp mlan $ */
33 #include <linux/version.h>
34 #include <linux/init.h>
35 #include <linux/errno.h>
36 #include <linux/module.h>
37 #include <linux/kernel.h>
38 #include <linux/major.h>
39 #include <linux/slab.h>
40 #include <linux/types.h>
41 #include <linux/pci.h>
42 #include <linux/delay.h>
43 #include <linux/vmalloc.h>
45 #include <linux/sched.h>
46 #include <linux/poll.h>
47 #include <linux/wrapper.h>
48 #include <linux/tqueue.h>
49 #include <linux/videodev.h>
50 #include <asm/uaccess.h>
53 #include <asm/dbdma.h>
54 #include <asm/pgtable.h>
57 #include <asm/semaphore.h>
59 /* Define these to get general / interrupt debugging */
66 #define DBG(x...) printk(KERN_DEBUG ## x)
71 #define IDBG(x...) printk(KERN_DEBUG ## x)
79 static struct planb planbs;
80 static volatile struct planb_registers *planb_regs;
82 static int def_norm = PLANB_DEF_NORM; /* default norm */
83 static int video_nr = -1;
84 static int vbi_nr = -1;
86 MODULE_PARM(def_norm, "i");
87 MODULE_PARM_DESC(def_norm, "Default startup norm (0=PAL, 1=NTSC, 2=SECAM)");
88 MODULE_PARM(video_nr,"i");
89 MODULE_PARM(vbi_nr,"i");
91 MODULE_DESCRIPTION("planb - v4l driver module for Apple PlanB video in");
92 MODULE_AUTHOR("Michel Lanners & Takashi Oe - see: http://www.cpu.lu/planb.html");
93 MODULE_LICENSE("GPL");
95 /* ------------------ PlanB Exported Functions ------------------ */
96 static long planb_write(struct video_device *, const char *, unsigned long, int);
97 static long planb_read(struct video_device *, char *, unsigned long, int);
98 static int planb_open(struct video_device *, int);
99 static void planb_close(struct video_device *);
100 static int planb_ioctl(struct video_device *, unsigned int, void *);
101 static int planb_mmap(struct video_device *, const char *, unsigned long);
102 static void planb_irq(int, void *, struct pt_regs *);
103 static int planb_vbi_open(struct video_device *, int);
104 static void planb_vbi_close(struct video_device *);
105 static long planb_vbi_read(struct video_device *, char *, unsigned long, int);
106 static unsigned int planb_vbi_poll(struct video_device *, struct file *,
108 static int planb_vbi_ioctl(struct video_device *, unsigned int, void *);
109 static void release_planb(void);
110 static int __init init_planbs(void);
111 static void __exit exit_planbs(void);
113 /* ------------------ PlanB Internal Functions ------------------ */
114 static int planb_prepare_open(struct planb *);
115 static int planb_prepare_vbi(struct planb *);
116 static int planb_prepare_video(struct planb *);
117 static void planb_prepare_close(struct planb *);
118 static void planb_close_vbi(struct planb *);
119 static void planb_close_video(struct planb *);
120 static void saa_write_reg(unsigned char, unsigned char);
121 static unsigned char saa_status(int, struct planb *);
122 static void saa_set(unsigned char, unsigned char, struct planb *);
123 static void saa_init_regs(struct planb *);
124 static int grabbuf_alloc(struct planb *);
125 static int vgrab(struct planb *, struct video_mmap *);
126 static void add_clip(struct planb *, struct video_clip *);
127 static void fill_cmd_buff(struct planb *);
128 static void cmd_buff(struct planb *);
129 static dbdma_cmd_ptr setup_grab_cmd(int, struct planb *);
130 static void overlay_start(struct planb *);
131 static void overlay_stop(struct planb *);
132 static inline void tab_cmd_dbdma(dbdma_cmd_ptr, unsigned short, unsigned int);
133 static inline void tab_cmd_store(dbdma_cmd_ptr, unsigned int, unsigned int);
134 static inline void tab_cmd_gen(dbdma_cmd_ptr, unsigned short, unsigned short,
135 unsigned int, unsigned int);
136 static int init_planb(struct planb *);
137 static int find_planb(void);
138 static void planb_pre_capture(int, struct planb *);
139 static dbdma_cmd_ptr cmd_geo_setup(dbdma_cmd_ptr, int, int, int, int, int,
141 static inline void planb_dbdma_stop(dbdma_regs_ptr);
142 static inline void planb_dbdma_restart(dbdma_regs_ptr);
143 static void saa_geo_setup(int, int, int, int, struct planb *);
144 static inline int overlay_is_active(struct planb *);
146 /*******************************/
147 /* Memory management functions */
148 /*******************************/
150 /* I know this is not the right way to allocate memory. Whoever knows
151 * the right way to allocate a huge buffer for DMA that can be mapped
152 * to user space, please tell me... or better, fix the code and send
155 * Michel Lanners (mlan@cpu.lu)
157 /* FIXME: As subsequent calls to __get_free_pages don't necessarily return
158 * contiguous pages, we need to do horrible things later on when setting
159 * up DMA, to make sure a single DMA transfer doesn't cross a page boundary.
160 * At least, I hope it's done right later on ;-) ......
161 * Anyway, there should be a way to get hold of a large buffer of contiguous
164 static int grabbuf_alloc(struct planb *pb)
168 npage = MAX_GBUFFERS * ((PLANB_MAX_FBUF / PAGE_SIZE + 1)
169 #ifndef PLANB_GSCANLINE
171 #endif /* PLANB_GSCANLINE */
173 if ((pb->rawbuf = (unsigned char**) kmalloc (npage
174 * sizeof(unsigned long), GFP_KERNEL)) == 0)
176 for (i = 0; i < npage; i++) {
177 pb->rawbuf[i] = (unsigned char *)__get_free_pages(GFP_KERNEL |
181 mem_map_reserve(virt_to_page(pb->rawbuf[i]));
184 DBG("PlanB: init_grab: grab buffer not allocated\n");
186 mem_map_unreserve(virt_to_page(pb->rawbuf[i]));
187 free_pages((unsigned long)pb->rawbuf[i], 0);
192 pb->rawbuf_nchunks = npage;
196 /*****************************/
197 /* Hardware access functions */
198 /*****************************/
200 static void saa_write_reg(unsigned char addr, unsigned char val)
202 planb_regs->saa_addr = addr; eieio();
203 planb_regs->saa_regval = val; eieio();
207 /* return status byte 0 or 1: */
208 static unsigned char saa_status(int byte, struct planb *pb)
210 saa_regs[pb->win.norm][SAA7196_STDC] =
211 (saa_regs[pb->win.norm][SAA7196_STDC] & ~2) | ((byte & 1) << 1);
212 saa_write_reg (SAA7196_STDC, saa_regs[pb->win.norm][SAA7196_STDC]);
214 /* Let's wait 30msec for this one */
215 current->state = TASK_INTERRUPTIBLE;
216 schedule_timeout(30 * HZ / 1000);
218 return (unsigned char)in_8 (&planb_regs->saa_status);
221 static void saa_set(unsigned char addr, unsigned char val, struct planb *pb)
223 if(saa_regs[pb->win.norm][addr] != val) {
224 saa_regs[pb->win.norm][addr] = val;
225 saa_write_reg (addr, val);
230 static void saa_init_regs(struct planb *pb)
234 for (i = 0; i < SAA7196_NUMREGS; i++)
235 saa_write_reg (i, saa_regs[pb->win.norm][i]);
238 static void saa_geo_setup(int width, int height, int interlace,
239 int fmt, struct planb *pb)
241 int ht, norm = pb->win.norm;
243 /* bits FS0, FS1 according to format spec */
244 saa_regs[norm][SAA7196_FMTS] &= ~0x3;
245 saa_regs[norm][SAA7196_FMTS] |= (palette2fmt[fmt].saa_fmt & 0x3);
247 ht = (interlace ? height / 2 : height);
248 saa_regs[norm][SAA7196_OUTPIX] = (unsigned char) (width & 0x00ff);
249 saa_regs[norm][SAA7196_HFILT] = (saa_regs[norm][SAA7196_HFILT] & ~0x3)
250 | (width >> 8 & 0x3);
251 saa_regs[norm][SAA7196_OUTLINE] = (unsigned char) (ht & 0xff);
252 saa_regs[norm][SAA7196_VYP] = (saa_regs[norm][SAA7196_VYP] & ~0x3)
254 /* feed both fields if interlaced, or else feed only even fields */
255 saa_regs[norm][SAA7196_FMTS] = (interlace) ?
256 (saa_regs[norm][SAA7196_FMTS] & ~0x60)
257 : (saa_regs[norm][SAA7196_FMTS] | 0x60);
258 /* transparent mode; extended format enabled */
259 saa_regs[norm][SAA7196_DPATH] |= 0x3;
260 /* bits LLV, MCT according to format spec */
261 saa_regs[norm][SAA7196_DPATH] &= ~0x30;
262 saa_regs[norm][SAA7196_DPATH] |= (palette2fmt[fmt].saa_fmt & 0x30);
265 /***************************/
266 /* DBDMA support functions */
267 /***************************/
269 static inline void planb_dbdma_restart(dbdma_regs_ptr ch)
271 writel(PLANB_CLR(RUN), &ch->control);
272 writel(PLANB_SET(RUN|WAKE) | PLANB_CLR(PAUSE), &ch->control);
275 static inline void planb_dbdma_stop(dbdma_regs_ptr ch)
279 writel(PLANB_CLR(RUN) | PLANB_SET(FLUSH), &ch->control);
280 while((readl(&ch->status) == (ACTIVE | FLUSH)) && (i < 999)) {
281 IDBG("PlanB: waiting for DMA to stop\n");
286 static inline void tab_cmd_dbdma(dbdma_cmd_ptr ch, unsigned short command,
287 unsigned int cmd_dep)
289 st_le16(&ch->command, command);
290 st_le16(&ch->req_count, 0);
291 st_le32(&ch->phy_addr, 0);
292 st_le32(&ch->cmd_dep, cmd_dep);
293 /* really clears res_count & xfer_status */
294 st_le32((unsigned int *)&ch->res_count, 0);
297 static inline void tab_cmd_store(dbdma_cmd_ptr ch, unsigned int phy_addr,
298 unsigned int cmd_dep)
300 st_le16(&ch->command, STORE_WORD | KEY_SYSTEM);
301 st_le16(&ch->req_count, 4);
302 st_le32(&ch->phy_addr, phy_addr);
303 st_le32(&ch->cmd_dep, cmd_dep);
304 st_le32((unsigned int *)&ch->res_count, 0);
307 static inline void tab_cmd_gen(dbdma_cmd_ptr ch, unsigned short command,
308 unsigned short req_count, unsigned int phy_addr, unsigned int cmd_dep)
310 st_le16(&ch->command, command);
311 st_le16(&ch->req_count, req_count);
312 st_le32(&ch->phy_addr, phy_addr);
313 st_le32(&ch->cmd_dep, cmd_dep);
314 st_le32((unsigned int *)&ch->res_count, 0);
317 static dbdma_cmd_ptr cmd_geo_setup(dbdma_cmd_ptr c1, int width, int height,
318 int interlace, int fmt, int clip, struct planb *pb)
320 int norm = pb->win.norm;
322 saa_geo_setup(width, height, interlace, fmt, pb);
323 /* if the number of DBDMA commands here (14) changes, lots of
324 * things need to be corrected accordingly... */
325 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->saa_addr),
327 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->saa_regval),
328 saa_regs[norm][SAA7196_FMTS]);
329 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->saa_addr),
331 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->saa_regval),
332 saa_regs[norm][SAA7196_DPATH]);
333 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->even),
334 palette2fmt[fmt].pb_fmt | ((clip)? PLANB_CLIPMASK: 0));
335 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->odd),
336 palette2fmt[fmt].pb_fmt | ((clip)? PLANB_CLIPMASK: 0));
337 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->saa_addr),
339 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->saa_regval),
340 saa_regs[norm][SAA7196_OUTPIX]);
341 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->saa_addr),
343 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->saa_regval),
344 saa_regs[norm][SAA7196_HFILT]);
345 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->saa_addr),
347 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->saa_regval),
348 saa_regs[norm][SAA7196_OUTLINE]);
349 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->saa_addr),
351 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->saa_regval),
352 saa_regs[norm][SAA7196_VYP]);
356 /******************************/
357 /* misc. supporting functions */
358 /******************************/
360 static inline void planb_lock(struct planb *pb)
362 DBG("PlanB: planb_lock\n");
366 static inline void planb_unlock(struct planb *pb)
368 DBG("PlanB: planb_unlock\n");
376 /* number of entries in the circular DBDMA command buffer
377 * initial stop, odd/even vbi, odd/even video, branch back */
379 static int planb_prepare_open(struct planb *pb)
384 size = (NUMJUMPS + 1) * sizeof(struct dbdma_cmd);
386 if((pb->jump_raw = kmalloc (size, GFP_KERNEL|GFP_DMA)) == 0)
388 memset(pb->jump_raw, 0, size);
389 c = pb->jumpbuf = (dbdma_cmd_ptr) DBDMA_ALIGN (pb->jump_raw);
391 /* circular DBDMA command buffer, to hold jumps to transfer commands */
392 tab_cmd_dbdma(c++, DBDMA_STOP, 0);
393 for (i=1; i<NUMJUMPS-1; i++)
394 tab_cmd_dbdma(c++, DBDMA_NOP, 0);
395 tab_cmd_dbdma(c, DBDMA_NOP|BR_ALWAYS,
396 (unsigned int)pb->jumpbuf);
398 DBG("PlanB: planb_prepare_open, jumpbuffer at 0x%08x, length %d.\n",
399 (unsigned int)pb->jumpbuf, size);
403 #define VBIDUMMY 40 /* must be even !! */
404 static int planb_prepare_vbi(struct planb *pb)
408 /* allocate VBI comand buffer memory
409 (2 fields * VBI_MAXLINES + 40 handling + alignment) */
410 size = (2*VBI_MAXLINES + VBIDUMMY + 1) * sizeof(struct dbdma_cmd);
412 if ((pb->vbi_raw = kmalloc (size, GFP_KERNEL|GFP_DMA)) == 0)
414 memset (pb->vbi_raw, 0, size);
415 size = (VBI_MAXLINES + VBIDUMMY/2) * sizeof(struct dbdma_cmd);
416 pb->vbi_cbo.start = (dbdma_cmd_ptr) DBDMA_ALIGN (pb->vbi_raw);
417 pb->vbi_cbo.size = pb->vbi_cbe.size = size;
418 pb->vbi_cbe.start = pb->vbi_cbo.start + pb->vbi_cbo.size;
419 pb->vbi_cbo.jumpaddr = pb->jumpbuf + 1;
420 pb->vbi_cbe.jumpaddr = pb->jumpbuf + 3;
422 DBG("PlanB: planb_prepare_vbi, dbdma cmd_buf at 0x%08x, length %d.\n",
423 (unsigned int)pb->vbi_cbo.start, 2*size);
427 static int planb_prepare_video(struct planb *pb)
431 /* FIXME: This is stressing kmalloc to its limits...
432 We really should allocate smaller chunks. */
434 /* allocate memory for two plus alpha command buffers (size: max lines,
435 plus 40 commands handling, plus 1 alignment), plus dummy command buf,
436 plus clipmask buffer, plus frame grabbing status */
437 size = (pb->tab_size * (2 + MAX_GBUFFERS * TAB_FACTOR)
438 + MAX_GBUFFERS * PLANB_DUMMY + 1) * sizeof(struct dbdma_cmd)
439 + (PLANB_MAXLINES * ((PLANB_MAXPIXELS + 7) & ~7)) / 8
440 + MAX_GBUFFERS * sizeof(unsigned int);
441 if ((pb->vid_raw = kmalloc (size, GFP_KERNEL|GFP_DMA)) == 0)
443 memset (pb->vid_raw, 0, size);
444 pb->vid_cbo.start = (dbdma_cmd_ptr) DBDMA_ALIGN (pb->vid_raw);
445 pb->vid_cbo.size = pb->vid_cbe.size = pb->tab_size/2;
446 pb->vid_cbe.start = pb->vid_cbo.start + pb->vid_cbo.size;
447 pb->vid_cbo.jumpaddr = pb->jumpbuf + 2;
448 pb->vid_cbe.jumpaddr = pb->jumpbuf + 4;
449 pb->overlay_last1 = pb->vid_cbo.start;
450 pb->vid_cbo.bus = virt_to_bus(pb->vid_cbo.start);
451 pb->vid_cbe.bus = virt_to_bus(pb->vid_cbe.start);
452 pb->clip_cbo.start = pb->vid_cbe.start + pb->vid_cbe.size;
453 pb->clip_cbo.size = pb->clip_cbe.size = pb->tab_size/2;
454 pb->clip_cbe.start = pb->clip_cbo.start + pb->clip_cbo.size;
455 pb->overlay_last2 = pb->clip_cbo.start;
456 pb->clip_cbo.bus = virt_to_bus(pb->clip_cbo.start);
457 pb->clip_cbe.bus = virt_to_bus(pb->clip_cbe.start);
458 pb->gbuf[0].cap_cmd = pb->clip_cbe.start + pb->clip_cbe.size;
459 pb->gbuf[0].pre_cmd = pb->gbuf[0].cap_cmd + pb->tab_size * TAB_FACTOR;
460 for (i = 1; i < MAX_GBUFFERS; i++) {
461 pb->gbuf[i].cap_cmd = pb->gbuf[i-1].pre_cmd + PLANB_DUMMY;
462 pb->gbuf[i].pre_cmd = pb->gbuf[i].cap_cmd +
463 pb->tab_size * TAB_FACTOR;
465 pb->gbuf[0].status = (volatile unsigned int *)
466 (pb->gbuf[MAX_GBUFFERS-1].pre_cmd + PLANB_DUMMY);
467 for (i = 1; i < MAX_GBUFFERS; i++)
468 pb->gbuf[i].status = pb->gbuf[i-1].status;
469 pb->mask = (unsigned char *)(pb->gbuf[MAX_GBUFFERS-1].status + 1);
472 pb->rawbuf_nchunks = 0;
474 for (i = 0; i < MAX_GBUFFERS; i++) {
475 gbuf_ptr gbuf = &pb->gbuf[i];
477 *gbuf->status = GBUFFER_UNUSED;
481 gbuf->norm_switch = 0;
482 #ifndef PLANB_GSCANLINE
490 pb->prev_last_fr = -999;
492 /* Reset DMA controllers */
493 planb_dbdma_stop(&pb->planb_base->ch2);
494 planb_dbdma_stop(&pb->planb_base->ch1);
496 DBG("PlanB: planb_prepare_video, dbdma cmd_buf at 0x%08x, "
497 "length %d.\n", (unsigned int)pb->vid_cbo.start, 2*size);
501 static void planb_prepare_close(struct planb *pb)
503 /* make sure the dma's are idle */
504 planb_dbdma_stop(&pb->planb_base->ch2);
505 planb_dbdma_stop(&pb->planb_base->ch1);
507 if(pb->jump_raw != 0) {
514 static void planb_close_vbi(struct planb *pb)
516 /* FIXME: stop running DMA */
518 /* Make sure the DMA controller doesn't jump here anymore */
519 tab_cmd_dbdma(pb->vbi_cbo.jumpaddr, DBDMA_NOP, 0);
520 tab_cmd_dbdma(pb->vbi_cbe.jumpaddr, DBDMA_NOP, 0);
522 if(pb->vbi_raw != 0) {
527 /* FIXME: deallocate VBI data buffer */
529 /* FIXME: restart running DMA if app. */
533 static void planb_close_video(struct planb *pb)
537 /* FIXME: stop running DMA */
539 /* Make sure the DMA controller doesn't jump here anymore */
540 tab_cmd_dbdma(pb->vid_cbo.jumpaddr, DBDMA_NOP, 0);
541 tab_cmd_dbdma(pb->vid_cbe.jumpaddr, DBDMA_NOP, 0);
542 /* No clipmask jumpbuffer yet */
544 tab_cmd_dbdma(pb->clip_cbo.jumpaddr, DBDMA_NOP, 0);
545 tab_cmd_dbdma(pb->clip_cbe.jumpaddr, DBDMA_NOP, 0);
548 if(pb->vid_raw != 0) {
551 pb->cmd_buff_inited = 0;
554 for (i = 0; i < pb->rawbuf_nchunks; i++) {
555 mem_map_unreserve(virt_to_page(pb->rawbuf[i]));
556 free_pages((unsigned long)pb->rawbuf[i], 0);
562 /* FIXME: restart running DMA if app. */
566 /*****************************/
567 /* overlay support functions */
568 /*****************************/
570 static void overlay_start(struct planb *pb)
572 DBG("PlanB: overlay_start()\n");
574 if(ACTIVE & readl(&pb->planb_base->ch1.status)) {
576 DBG("PlanB: presumably, grabbing is in progress...\n");
578 planb_dbdma_stop(&pb->planb_base->ch2);
579 writel(pb->clip_cbo.bus, &pb->planb_base->ch2.cmdptr);
580 planb_dbdma_restart(&pb->planb_base->ch2);
581 st_le16 (&pb->vid_cbo.start->command, DBDMA_NOP);
582 tab_cmd_dbdma(pb->gbuf[pb->last_fr].last_cmd,
583 DBDMA_NOP | BR_ALWAYS, pb->vid_cbo.bus);
585 pb->prev_last_fr = pb->last_fr;
587 if(!(ACTIVE & readl(&pb->planb_base->ch1.status))) {
588 IDBG("PlanB: became inactive "
589 "in the mean time... reactivating\n");
590 planb_dbdma_stop(&pb->planb_base->ch1);
591 writel(pb->vid_cbo.bus, &pb->planb_base->ch1.cmdptr);
592 planb_dbdma_restart(&pb->planb_base->ch1);
596 DBG("PlanB: currently idle, so can do whatever\n");
598 planb_dbdma_stop(&pb->planb_base->ch2);
599 planb_dbdma_stop(&pb->planb_base->ch1);
600 st_le32(&pb->planb_base->ch2.cmdptr, pb->clip_cbo.bus);
601 st_le32(&pb->planb_base->ch1.cmdptr, pb->vid_cbo.bus);
602 writew(DBDMA_NOP, &pb->vid_cbo.start->command);
603 planb_dbdma_restart(&pb->planb_base->ch2);
604 planb_dbdma_restart(&pb->planb_base->ch1);
610 static void overlay_stop(struct planb *pb)
612 DBG("PlanB: overlay_stop()\n");
614 if(pb->last_fr == -1) {
616 DBG("PlanB: no grabbing, it seems...\n");
618 planb_dbdma_stop(&pb->planb_base->ch2);
619 planb_dbdma_stop(&pb->planb_base->ch1);
621 } else if(pb->last_fr == -2) {
622 unsigned int cmd_dep;
623 tab_cmd_dbdma(pb->gbuf[pb->prev_last_fr].cap_cmd, DBDMA_STOP, 0);
625 cmd_dep = (unsigned int)readl(&pb->overlay_last1->cmd_dep);
626 if(overlay_is_active(pb)) {
628 DBG("PlanB: overlay is currently active\n");
630 planb_dbdma_stop(&pb->planb_base->ch2);
631 planb_dbdma_stop(&pb->planb_base->ch1);
632 if(cmd_dep != pb->vid_cbo.bus) {
633 writel(virt_to_bus(pb->overlay_last1),
634 &pb->planb_base->ch1.cmdptr);
635 planb_dbdma_restart(&pb->planb_base->ch1);
638 pb->last_fr = pb->prev_last_fr;
639 pb->prev_last_fr = -999;
644 static void suspend_overlay(struct planb *pb)
647 struct dbdma_cmd last;
649 DBG("PlanB: suspend_overlay: %d\n", pb->suspend);
653 if(ACTIVE & readl(&pb->planb_base->ch1.status)) {
654 if(pb->last_fr == -2) {
655 fr = pb->prev_last_fr;
656 memcpy(&last, (void*)pb->gbuf[fr].last_cmd, sizeof(last));
657 tab_cmd_dbdma(pb->gbuf[fr].last_cmd, DBDMA_STOP, 0);
659 if(overlay_is_active(pb)) {
660 planb_dbdma_stop(&pb->planb_base->ch2);
661 planb_dbdma_stop(&pb->planb_base->ch1);
662 pb->suspended.overlay = 1;
663 pb->suspended.frame = fr;
664 memcpy(&pb->suspended.cmd, &last, sizeof(last));
668 pb->suspended.overlay = 0;
669 pb->suspended.frame = fr;
670 memcpy(&pb->suspended.cmd, &last, sizeof(last));
674 static void resume_overlay(struct planb *pb)
677 DBG("PlanB: resume_overlay: %d\n", pb->suspend);
681 if(pb->suspended.frame != -1) {
682 memcpy((void*)pb->gbuf[pb->suspended.frame].last_cmd,
683 &pb->suspended.cmd, sizeof(pb->suspended.cmd));
685 if(ACTIVE & readl(&pb->planb_base->ch1.status)) {
688 if(pb->suspended.overlay) {
690 DBG("PlanB: overlay being resumed\n");
692 st_le16 (&pb->vid_cbo.start->command, DBDMA_NOP);
693 st_le16 (&pb->clip_cbo.start->command, DBDMA_NOP);
694 /* Set command buffer addresses */
695 writel(virt_to_bus(pb->overlay_last1),
696 &pb->planb_base->ch1.cmdptr);
697 writel(virt_to_bus(pb->overlay_last2),
698 &pb->planb_base->ch2.cmdptr);
699 /* Start the DMA controller */
700 writel(PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE),
701 &pb->planb_base->ch2.control);
702 writel(PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE),
703 &pb->planb_base->ch1.control);
704 } else if(pb->suspended.frame != -1) {
705 writel(virt_to_bus(pb->gbuf[pb->suspended.frame].last_cmd),
706 &pb->planb_base->ch1.cmdptr);
707 writel(PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE),
708 &pb->planb_base->ch1.control);
713 wake_up_interruptible(&pb->suspendq);
716 static void add_clip(struct planb *pb, struct video_clip *clip)
718 volatile unsigned char *base;
719 int xc = clip->x, yc = clip->y;
720 int wc = clip->width, hc = clip->height;
721 int ww = pb->win.width, hw = pb->win.height;
722 int x, y, xtmp1, xtmp2;
724 DBG("PlanB: clip %dx%d+%d+%d\n", wc, hc, xc, yc);
736 if(wc <= 0) /* Nothing to do */
741 for (y = yc; y < yc+hc; y++) {
744 base = pb->mask + y*96;
745 if(xc != 0 || wc >= 8)
746 *(base + xtmp1) &= (unsigned char)(0x00ff &
748 for (x = xtmp1 + 1; x < xtmp2; x++) {
752 *(base + xtmp2) &= (unsigned char)(0x00ff >>
759 static void fill_cmd_buff(struct planb *pb)
764 DBG("PlanB: fill_cmd_buff()\n");
766 if(pb->overlay_last1 != pb->vid_cbo.start) {
768 last = *(pb->overlay_last1);
770 memset ((void *) pb->vid_cbo.start, 0, 2 * pb->tab_size
771 * sizeof(struct dbdma_cmd));
774 *(pb->overlay_last1) = last;
775 if(pb->suspended.overlay) {
776 unsigned long jump_addr = readl(&pb->overlay_last1->cmd_dep);
777 if(jump_addr != pb->vid_cbo.bus) {
780 DBG("PlanB: adjusting ch1's jump address\n");
782 for(i = 0; i < MAX_GBUFFERS; i++) {
783 if(pb->gbuf[i].need_pre_capture) {
784 if(jump_addr == virt_to_bus(pb->gbuf[i].pre_cmd))
788 virt_to_bus(pb->gbuf[i].cap_cmd))
793 DBG(" not found!\n");
797 if(pb->gbuf[i].need_pre_capture)
798 writel(virt_to_bus(pb->overlay_last1),
799 &pb->gbuf[i].pre_cmd->phy_addr);
801 writel(virt_to_bus(pb->overlay_last1),
802 &pb->gbuf[i].cap_cmd->phy_addr);
806 pb->cmd_buff_inited = 1;
811 static void cmd_buff(struct planb *pb)
813 int i, bpp, count, nlines, stepsize, interlace;
814 unsigned long base, jump, addr_com, addr_dep;
815 dbdma_cmd_ptr c1 = pb->vid_cbo.start;
816 dbdma_cmd_ptr c2 = pb->clip_cbo.start;
818 interlace = pb->win.interlace;
820 count = (bpp * ((pb->win.x + pb->win.width > pb->win.swidth) ?
821 (pb->win.swidth - pb->win.x) : pb->win.width));
822 nlines = ((pb->win.y + pb->win.height > pb->win.sheight) ?
823 (pb->win.sheight - pb->win.y) : pb->win.height);
827 /* Preamble commands: */
828 addr_com = virt_to_bus(c1);
829 addr_dep = virt_to_bus(&c1->cmd_dep);
830 tab_cmd_dbdma(c1++, DBDMA_NOP, 0);
831 jump = virt_to_bus(c1+16); /* 14 by cmd_geo_setup() and 2 for padding */
832 c1 = cmd_geo_setup(c1, pb->win.width, pb->win.height, interlace,
833 pb->win.color_fmt, 1, pb);
834 tab_cmd_store(c1++, addr_com, (unsigned)(DBDMA_NOP | BR_ALWAYS) << 16);
835 tab_cmd_store(c1++, addr_dep, jump);
836 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.wait_sel),
837 PLANB_SET(FIELD_SYNC));
838 /* (1) wait for field sync to be set */
839 tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
840 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),
841 PLANB_SET(ODD_FIELD));
842 /* wait for field sync to be cleared */
843 tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
844 /* if not odd field, wait until field sync is set again */
845 tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;
846 /* assert ch_sync to ch2 */
847 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch2.control),
849 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),
850 PLANB_SET(DMA_ABORT));
852 base = (pb->fb.phys + pb->fb.offset + pb->win.y * (pb->win.bpl +
853 pb->win.pad) + pb->win.x * bpp);
857 jump = virt_to_bus(c1 + (nlines + 1) / 2);
860 jump = virt_to_bus(c1 + nlines);
863 /* even field data: */
864 for (i=0; i < nlines; i += stepsize, c1++)
865 tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET,
866 count, base + i * (pb->win.bpl + pb->win.pad), jump);
868 /* For non-interlaced, we use even fields only */
870 goto cmd_tab_data_end;
872 /* Resync to odd field */
873 /* (2) wait for field sync to be set */
874 tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
875 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),
876 PLANB_SET(ODD_FIELD));
877 /* wait for field sync to be cleared */
878 tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
879 /* if not odd field, wait until field sync is set again */
880 tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;
881 /* assert ch_sync to ch2 */
882 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch2.control),
884 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),
885 PLANB_SET(DMA_ABORT));
887 /* odd field data: */
888 jump = virt_to_bus(c1 + nlines / 2);
889 for (i=1; i < nlines; i += stepsize, c1++)
890 tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,
891 base + i * (pb->win.bpl + pb->win.pad), jump);
893 /* And jump back to the start */
895 pb->overlay_last1 = c1; /* keep a pointer to the last command */
896 tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, pb->vid_cbo.bus);
898 /* Clipmask command buffer */
900 /* Preamble commands: */
901 tab_cmd_dbdma(c2++, DBDMA_NOP, 0);
902 tab_cmd_store(c2++, (unsigned)(&pb->planb_base_bus->ch2.wait_sel),
904 /* wait until ch1 asserts ch_sync */
905 tab_cmd_dbdma(c2++, DBDMA_NOP | WAIT_IFCLR, 0);
906 /* clear ch_sync asserted by ch1 */
907 tab_cmd_store(c2++, (unsigned)(&pb->planb_base_bus->ch2.control),
909 tab_cmd_store(c2++, (unsigned)(&pb->planb_base_bus->ch2.wait_sel),
910 PLANB_SET(FIELD_SYNC));
911 tab_cmd_store(c2++, (unsigned)(&pb->planb_base_bus->ch2.br_sel),
912 PLANB_SET(ODD_FIELD));
914 /* jump to end of even field if appropriate */
915 /* this points to (interlace)? pos. C: pos. B */
916 jump = (interlace) ? virt_to_bus(c2 + (nlines + 1) / 2 + 2):
917 virt_to_bus(c2 + nlines + 2);
918 /* if odd field, skip over to odd field clipmasking */
919 tab_cmd_dbdma(c2++, DBDMA_NOP | BR_IFSET, jump);
921 /* even field mask: */
922 tab_cmd_store(c2++, (unsigned)(&pb->planb_base_bus->ch2.br_sel),
923 PLANB_SET(DMA_ABORT));
924 /* this points to pos. B */
925 jump = (interlace) ? virt_to_bus(c2 + nlines + 1):
926 virt_to_bus(c2 + nlines);
927 base = virt_to_bus(pb->mask);
928 for (i=0; i < nlines; i += stepsize, c2++)
929 tab_cmd_gen(c2, OUTPUT_MORE | KEY_STREAM0 | BR_IFSET, 96,
930 base + i * 96, jump);
932 /* For non-interlaced, we use only even fields */
934 goto cmd_tab_mask_end;
936 /* odd field mask: */
937 /* C */ tab_cmd_store(c2++, (unsigned)(&pb->planb_base_bus->ch2.br_sel),
938 PLANB_SET(DMA_ABORT));
939 /* this points to pos. B */
940 jump = virt_to_bus(c2 + nlines / 2);
941 base = virt_to_bus(pb->mask);
942 for (i=1; i < nlines; i += 2, c2++) /* abort if set */
943 tab_cmd_gen(c2, OUTPUT_MORE | KEY_STREAM0 | BR_IFSET, 96,
944 base + i * 96, jump);
946 /* Inform channel 1 and jump back to start */
948 /* ok, I just realized this is kind of flawed. */
949 /* this part is reached only after odd field clipmasking. */
950 /* wanna clean up? */
951 /* wait for field sync to be set */
952 /* corresponds to fsync (1) of ch1 */
953 /* B */ tab_cmd_dbdma(c2++, DBDMA_NOP | WAIT_IFCLR, 0);
954 /* restart ch1, meant to clear any dead bit or something */
955 tab_cmd_store(c2++, (unsigned)(&pb->planb_base_bus->ch1.control),
957 tab_cmd_store(c2++, (unsigned)(&pb->planb_base_bus->ch1.control),
959 pb->overlay_last2 = c2; /* keep a pointer to the last command */
960 /* start over even field clipmasking */
961 tab_cmd_dbdma(c2, DBDMA_NOP | BR_ALWAYS, pb->clip_cbo.bus);
967 /*********************************/
968 /* grabdisplay support functions */
969 /*********************************/
971 static inline int overlay_is_active(struct planb *pb)
973 unsigned int size = pb->tab_size * sizeof(struct dbdma_cmd);
974 unsigned int caddr = (unsigned)readl(&pb->planb_base->ch1.cmdptr);
976 return (readl(&pb->overlay_last1->cmd_dep) == pb->vid_cbo.bus)
977 && (caddr < (pb->vid_cbo.bus + size))
978 && (caddr >= (unsigned)pb->vid_cbo.bus);
981 static int vgrab(struct planb *pb, struct video_mmap *mp)
983 unsigned int fr = mp->frame;
984 unsigned int fmt = mp->format;
985 unsigned int bpp = palette2fmt[fmt].bpp;
986 gbuf_ptr gbuf = &pb->gbuf[fr];
988 if(pb->rawbuf==NULL) {
990 if((err=grabbuf_alloc(pb)))
994 DBG("PlanB: grab %d: %dx%d fmt %d (%u)\n", pb->grabbing, mp->width,
995 mp->height, fmt, fr);
997 if(pb->grabbing >= MAX_GBUFFERS) {
1001 if(fr > (MAX_GBUFFERS - 1) || fr < 0) {
1002 DBG(" invalid buffer\n");
1005 if(mp->height <= 0 || mp->width <= 0) {
1006 DBG(" negative height or width\n");
1009 if(mp->format < 0 || mp->format >= PLANB_PALETTE_MAX) {
1010 DBG(" format out of range\n");
1014 DBG(" unsupported format %d\n", mp->format);
1017 if (mp->height * mp->width * bpp > PLANB_MAX_FBUF) {
1018 DBG(" grab bigger than buffer\n");
1023 if(mp->width != gbuf->width || mp->height != gbuf->height ||
1024 fmt != gbuf->fmt || (gbuf->norm_switch)) {
1026 #ifndef PLANB_GSCANLINE
1027 unsigned int osize = gbuf->width * gbuf->height *
1028 palette2fmt[gbuf->fmt].bpp;
1029 unsigned int nsize = mp->width * mp->height * bpp;
1032 DBG("PlanB: changed gwidth = %d, gheight = %d, format = %u, "
1033 "osize = %d, nsize = %d\n", mp->width, mp->height, fmt,
1036 /* Do we _really_ need to clear the grab buffers?? */
1038 #ifndef PLANB_GSCANLINE
1039 if(gbuf->norm_switch)
1041 if (nsize < osize) {
1042 for(i = gbuf->idx; osize > 0; i++) {
1043 memset((void *)pb->rawbuf[i], 0, PAGE_SIZE);
1047 for(i = gbuf->l_fr_addr_idx; i <
1048 gbuf->l_fr_addr_idx + gbuf->lnum; i++)
1049 memset((void *)pb->rawbuf[i], 0, PAGE_SIZE);
1053 if(gbuf->norm_switch)
1054 memset((void *)pb->gbuffer[fr], 0,
1055 pb->gbytes_per_line * gbuf->height);
1058 for(i = 0; i < gbuf->height; i++) {
1059 memset((void *)(pb->gbuffer[fr]
1060 + pb->gbytes_per_line * i
1066 gbuf->width = mp->width;
1067 gbuf->height = mp->height;
1069 gbuf->last_cmd = setup_grab_cmd(fr, pb);
1070 planb_pre_capture(fr, pb);
1071 gbuf->need_pre_capture = 1;
1072 gbuf->norm_switch = 0;
1074 gbuf->need_pre_capture = 0;
1076 *gbuf->status = GBUFFER_GRABBING;
1077 if(!(ACTIVE & readl(&pb->planb_base->ch1.status))) {
1079 IDBG("PlanB: ch1 inactive, initiating grabbing\n");
1081 planb_dbdma_stop(&pb->planb_base->ch1);
1082 if(gbuf->need_pre_capture) {
1084 DBG("PlanB: padding pre-capture sequence\n");
1086 writel(virt_to_bus(gbuf->pre_cmd),
1087 &pb->planb_base->ch1.cmdptr);
1089 tab_cmd_dbdma(gbuf->last_cmd, DBDMA_STOP, 0);
1090 tab_cmd_dbdma(gbuf->cap_cmd, DBDMA_NOP, 0);
1091 /* let's be on the safe side. here is not timing critical. */
1092 tab_cmd_dbdma((gbuf->cap_cmd + 1), DBDMA_NOP, 0);
1093 writel(virt_to_bus(gbuf->cap_cmd),
1094 &pb->planb_base->ch1.cmdptr);
1096 planb_dbdma_restart(&pb->planb_base->ch1);
1101 DBG("PlanB: ch1 active, grabbing being queued\n");
1103 if((pb->last_fr == -1) || ((pb->last_fr == -2) &&
1104 overlay_is_active(pb))) {
1106 DBG("PlanB: overlay is active, grabbing defered\n");
1108 tab_cmd_dbdma(gbuf->last_cmd, DBDMA_NOP | BR_ALWAYS,
1110 if(gbuf->need_pre_capture) {
1112 DBG("PlanB: padding pre-capture sequence\n");
1114 tab_cmd_store(gbuf->pre_cmd,
1115 virt_to_bus(&pb->overlay_last1->cmd_dep),
1118 writel(virt_to_bus(gbuf->pre_cmd),
1119 &pb->overlay_last1->cmd_dep);
1121 tab_cmd_store(gbuf->cap_cmd,
1122 virt_to_bus(&pb->overlay_last1->cmd_dep),
1124 tab_cmd_dbdma((gbuf->cap_cmd + 1),
1127 writel(virt_to_bus(gbuf->cap_cmd),
1128 &pb->overlay_last1->cmd_dep);
1130 for(i = 0; overlay_is_active(pb) && i < 999; i++)
1131 DBG("PlanB: waiting for overlay done\n");
1132 tab_cmd_dbdma(pb->vid_cbo.start, DBDMA_NOP, 0);
1133 pb->prev_last_fr = fr;
1135 } else if(pb->last_fr == -2) {
1137 DBG("PlanB: mixed mode detected, grabbing"
1138 " will be done before activating overlay\n");
1140 tab_cmd_dbdma(pb->vid_cbo.start, DBDMA_NOP, 0);
1141 if(gbuf->need_pre_capture) {
1143 DBG("PlanB: padding pre-capture sequence\n");
1145 tab_cmd_dbdma(pb->gbuf[pb->prev_last_fr].last_cmd,
1146 DBDMA_NOP | BR_ALWAYS,
1147 virt_to_bus(gbuf->pre_cmd));
1150 tab_cmd_dbdma(gbuf->cap_cmd, DBDMA_NOP, 0);
1151 if(pb->gbuf[pb->prev_last_fr].width !=
1153 || pb->gbuf[pb->prev_last_fr].height !=
1155 || pb->gbuf[pb->prev_last_fr].fmt !=
1157 tab_cmd_dbdma((gbuf->cap_cmd + 1),
1160 tab_cmd_dbdma((gbuf->cap_cmd + 1),
1161 DBDMA_NOP | BR_ALWAYS,
1162 virt_to_bus(gbuf->cap_cmd + 16));
1163 tab_cmd_dbdma(pb->gbuf[pb->prev_last_fr].last_cmd,
1164 DBDMA_NOP | BR_ALWAYS,
1165 virt_to_bus(gbuf->cap_cmd));
1168 tab_cmd_dbdma(gbuf->last_cmd, DBDMA_NOP | BR_ALWAYS,
1171 pb->prev_last_fr = fr;
1174 gbuf_ptr lastgbuf = &pb->gbuf[pb->last_fr];
1176 DBG("PlanB: active grabbing session detected\n");
1178 if(gbuf->need_pre_capture) {
1180 DBG("PlanB: padding pre-capture sequence\n");
1182 tab_cmd_dbdma(lastgbuf->last_cmd,
1183 DBDMA_NOP | BR_ALWAYS,
1184 virt_to_bus(gbuf->pre_cmd));
1187 tab_cmd_dbdma(gbuf->last_cmd, DBDMA_STOP, 0);
1188 tab_cmd_dbdma(gbuf->cap_cmd, DBDMA_NOP, 0);
1189 if(lastgbuf->width != gbuf->width
1190 || lastgbuf->height != gbuf->height
1191 || lastgbuf->fmt != gbuf->fmt)
1192 tab_cmd_dbdma((gbuf->cap_cmd + 1),
1195 tab_cmd_dbdma((gbuf->cap_cmd + 1),
1196 DBDMA_NOP | BR_ALWAYS,
1197 virt_to_bus(gbuf->cap_cmd + 16));
1198 tab_cmd_dbdma(lastgbuf->last_cmd,
1199 DBDMA_NOP | BR_ALWAYS,
1200 virt_to_bus(gbuf->cap_cmd));
1205 if(!(ACTIVE & readl(&pb->planb_base->ch1.status))) {
1207 DBG("PlanB: became inactive in the mean time... "
1210 planb_dbdma_stop(&pb->planb_base->ch1);
1211 writel(virt_to_bus(gbuf->cap_cmd),
1212 &pb->planb_base->ch1.cmdptr);
1213 planb_dbdma_restart(&pb->planb_base->ch1);
1222 static void planb_pre_capture(int fr, struct planb *pb)
1224 gbuf_ptr gbuf = &pb->gbuf[fr];
1225 dbdma_cmd_ptr c1 = gbuf->pre_cmd;
1226 int height = gbuf->height;
1227 int interlace = (height > pb->maxlines/2)? 1: 0;
1229 tab_cmd_dbdma(c1++, DBDMA_NOP, 0);
1230 c1 = cmd_geo_setup(c1, gbuf->width, height, interlace, gbuf->fmt,
1232 /* Sync to even field */
1233 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.wait_sel),
1234 PLANB_SET(FIELD_SYNC));
1235 tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
1236 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),
1237 PLANB_SET(ODD_FIELD));
1238 tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
1239 tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;
1240 tab_cmd_dbdma(c1++, DBDMA_NOP | INTR_ALWAYS, 0);
1241 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),
1242 PLANB_SET(DMA_ABORT));
1243 /* For non-interlaced, we use even fields only */
1245 goto cmd_tab_data_end;
1246 /* Sync to odd field */
1247 tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
1248 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),
1249 PLANB_SET(ODD_FIELD));
1250 tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
1251 tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;
1252 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),
1253 PLANB_SET(DMA_ABORT));
1255 tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(gbuf->cap_cmd));
1260 /* This needs some explanation.
1261 * What we do here is write the DBDMA commands to fill the grab buffer.
1262 * Since the grab buffer is made up of physically non-contiguous chunks,
1263 * we need to make sure to not make the DMA engine write across a chunk
1264 * boundary: the DMA engine needs a physically contiguous memory chunk for
1265 * a single scan line.
1266 * So all those scan lines that cross a chunk boundary are written do spare
1267 * scratch buffers, and we keep track of this fact.
1268 * Later, in the interrupt routine, we copy those scan lines (in two pieces)
1269 * back to where they belong in the right sequence in the grab buffer.
1271 static dbdma_cmd_ptr setup_grab_cmd(int fr, struct planb *pb)
1273 int i, count, nlines, stepsize, interlace;
1274 #ifdef PLANB_GSCANLINE
1277 int nlpp, leftover1;
1283 dbdma_cmd_ptr jump_addr;
1284 gbuf_ptr gbuf = &pb->gbuf[fr];
1285 int fmt = gbuf->fmt;
1288 nlines = gbuf->height;
1289 interlace = (nlines > pb->maxlines/2) ? 1 : 0;
1290 count = palette2fmt[fmt].bpp * gbuf->width;
1291 #ifdef PLANB_GSCANLINE
1292 scanline = pb->gbytes_per_line;
1294 gbuf->lsize = count;
1300 /* Preamble commands: */
1301 tab_cmd_dbdma(c1++, DBDMA_NOP, 0);
1302 tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(c1 + 16)); c1++;
1303 c1 = cmd_geo_setup(c1, gbuf->width, nlines, interlace, fmt, 0, pb);
1304 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.wait_sel),
1305 PLANB_SET(FIELD_SYNC));
1306 tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
1307 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),
1308 PLANB_SET(ODD_FIELD));
1309 tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
1310 tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;
1311 tab_cmd_dbdma(c1++, DBDMA_NOP | INTR_ALWAYS, 0);
1312 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),
1313 PLANB_SET(DMA_ABORT));
1317 jump_addr = c1 + TAB_FACTOR * (nlines + 1) / 2;
1320 jump_addr = c1 + TAB_FACTOR * nlines;
1322 jump = virt_to_bus(jump_addr);
1324 /* even field data: */
1327 #ifdef PLANB_GSCANLINE
1328 for (i = 0; i < nlines; i += stepsize) {
1329 tab_cmd_gen(c1++, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,
1330 virt_to_bus(pb->rawbuf[pagei + i * scanline / PAGE_SIZE]),
1339 base = virt_to_bus(pb->rawbuf[pagei]);
1340 nlpp = (PAGE_SIZE - leftover1) / count / stepsize;
1341 for(j = 0; j < nlpp && i < nlines; j++, i += stepsize, c1++)
1342 tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET,
1343 count, base + count * j * stepsize + leftover1, jump);
1345 int lov0 = PAGE_SIZE - count * nlpp * stepsize - leftover1;
1351 /* can happen only when interlacing; then other field
1352 * uses up leftover space (lov0 - count). */
1353 tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count, base
1354 + count * nlpp * stepsize + leftover1, jump);
1356 /* start of free space at end of page: */
1357 pb->l_to_addr[fr][gbuf->lnum] = pb->rawbuf[pagei]
1358 + count * nlpp * stepsize + leftover1;
1359 /* index where continuation is: */
1360 pb->l_to_next_idx[fr][gbuf->lnum] = pagei + 1;
1361 /* How much is left to do in next page: */
1362 pb->l_to_next_size[fr][gbuf->lnum] = count - lov0;
1363 tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,
1364 virt_to_bus(pb->rawbuf[gbuf->l_fr_addr_idx
1365 + gbuf->lnum]), jump);
1366 if(++gbuf->lnum > MAX_LNUM) {
1367 /* FIXME: error condition! */
1371 leftover1 = count * stepsize - lov0;
1376 } while(i < nlines);
1377 tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, jump);
1379 #endif /* PLANB_GSCANLINE */
1381 /* For non-interlaced, we use even fields only */
1383 goto cmd_tab_data_end;
1385 /* Sync to odd field */
1386 tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
1387 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),
1388 PLANB_SET(ODD_FIELD));
1389 tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
1390 tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;
1391 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),
1392 PLANB_SET(DMA_ABORT));
1394 /* odd field data: */
1395 jump_addr = c1 + TAB_FACTOR * nlines / 2;
1396 jump = virt_to_bus(jump_addr);
1397 #ifdef PLANB_GSCANLINE
1398 for (i = 1; i < nlines; i += stepsize) {
1399 tab_cmd_gen(c1++, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,
1400 virt_to_bus(pb->rawbuf[pagei
1401 + i * scanline / PAGE_SIZE]), jump);
1412 base = virt_to_bus(pb->rawbuf[pagei]);
1413 nlpp = (PAGE_SIZE - leftover1) / count / stepsize;
1414 if(leftover1 >= count) {
1415 tab_cmd_gen(c1++, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,
1416 base + leftover1 - count, jump);
1419 for(j = 0; j < nlpp && i < nlines; j++, i += stepsize, c1++)
1420 tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,
1421 base + count * (j * stepsize + 1) + leftover1, jump);
1423 int lov0 = PAGE_SIZE - count * nlpp * stepsize - leftover1;
1429 pb->l_to_addr[fr][gbuf->lnum] = pb->rawbuf[pagei]
1430 + count * (nlpp * stepsize + 1) + leftover1;
1431 pb->l_to_next_idx[fr][gbuf->lnum] = pagei + 1;
1432 pb->l_to_next_size[fr][gbuf->lnum] = count * stepsize
1434 tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,
1435 virt_to_bus(pb->rawbuf[gbuf->l_fr_addr_idx
1436 + gbuf->lnum]), jump);
1437 if(++gbuf->lnum > MAX_LNUM) {
1438 /* FIXME: error condition! */
1443 leftover1 = count * stepsize - lov0;
1447 } while(i < nlines);
1449 tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, jump);
1451 #endif /* PLANB_GSCANLINE */
1454 tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->intr_stat),
1455 (fr << 9) | PLANB_FRM_IRQ | PLANB_GEN_IRQ);
1457 tab_cmd_dbdma(c1, DBDMA_STOP, 0);
1463 static void planb_irq(int irq, void *dev_id, struct pt_regs * regs)
1465 unsigned int stat, astat;
1466 struct planb *pb = (struct planb *)dev_id;
1468 IDBG("PlanB: planb_irq()\n");
1470 /* get/clear interrupt status bits */
1472 stat = readl(&pb->planb_base->intr_stat);
1473 astat = stat & pb->intr_mask;
1474 writel(PLANB_FRM_IRQ & ~astat & stat & ~PLANB_GEN_IRQ,
1475 &pb->planb_base->intr_stat);
1476 IDBG("PlanB: stat = %X, astat = %X\n", stat, astat);
1478 if(astat & PLANB_FRM_IRQ) {
1479 unsigned int fr = stat >> 9;
1480 gbuf_ptr gbuf = &pb->gbuf[fr];
1481 #ifndef PLANB_GSCANLINE
1484 IDBG("PlanB: PLANB_FRM_IRQ\n");
1488 IDBG("PlanB: grab %d: fr = %d, gcount = %d\n",
1489 pb->grabbing, fr, pb->gcount);
1490 #ifndef PLANB_GSCANLINE
1491 /* Now that the buffer is full, copy those lines that fell
1492 * on a page boundary from the spare buffers back to where
1494 IDBG("PlanB: %d * %d bytes are being copied over\n",
1495 gbuf->lnum, gbuf->lsize);
1496 for(i = 0; i < gbuf->lnum; i++) {
1497 int first = gbuf->lsize - pb->l_to_next_size[fr][i];
1499 memcpy(pb->l_to_addr[fr][i],
1500 pb->rawbuf[gbuf->l_fr_addr_idx + i],
1502 memcpy(pb->rawbuf[pb->l_to_next_idx[fr][i]],
1503 pb->rawbuf[gbuf->l_fr_addr_idx + i] + first,
1504 pb->l_to_next_size[fr][i]);
1507 *gbuf->status = GBUFFER_DONE;
1509 wake_up_interruptible(&pb->capq);
1512 /* incorrect interrupts? */
1513 pb->intr_mask = PLANB_CLR_IRQ;
1514 writel(PLANB_CLR_IRQ, &pb->planb_base->intr_stat);
1515 printk(KERN_ERR "PlanB: IRQ lockup, cleared interrupts"
1516 " unconditionally\n");
1519 /*******************************
1520 * Device Operations functions *
1521 *******************************/
1523 static int planb_open(struct video_device *dev, int mode)
1525 struct planb *pb = (struct planb *)dev->priv;
1528 /* first open on driver? */
1529 if(pb->vid_user + pb->vbi_user == 0) {
1530 if((err = planb_prepare_open(pb)) != 0)
1533 /* first open on video dev? */
1534 if(pb->vid_user == 0) {
1535 if((err = planb_prepare_video(pb)) != 0)
1540 DBG("PlanB: device opened\n");
1546 static void planb_close(struct video_device *dev)
1548 struct planb *pb = (struct planb *)dev->priv;
1551 /* last close? then stop everything... */
1552 if(--pb->vid_user == 0) {
1554 planb_dbdma_stop(&pb->planb_base->ch2);
1555 planb_dbdma_stop(&pb->planb_base->ch1);
1558 planb_close_video(pb);
1560 /* last open on PlanB hardware? */
1561 if(pb->vid_user + pb->vbi_user == 0)
1562 planb_prepare_close(pb);
1565 DBG("PlanB: device closed\n");
1571 static long planb_read(struct video_device *v, char *buf, unsigned long count,
1574 DBG("planb: read request\n");
1578 static long planb_write(struct video_device *v, const char *buf,
1579 unsigned long count, int nonblock)
1581 DBG("planb: write request\n");
1585 static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
1587 struct planb *pb=(struct planb *)dev->priv;
1593 struct video_capability b;
1595 DBG("PlanB: IOCTL VIDIOCGCAP\n");
1597 strcpy (b.name, pb->video_dev.name);
1598 b.type = VID_TYPE_OVERLAY | VID_TYPE_CLIPPING |
1599 VID_TYPE_FRAMERAM | VID_TYPE_SCALES |
1601 b.channels = 2; /* composite & svhs */
1603 b.maxwidth = PLANB_MAXPIXELS;
1604 b.maxheight = PLANB_MAXLINES;
1605 b.minwidth = 32; /* wild guess */
1607 if (copy_to_user(arg,&b,sizeof(b)))
1613 struct video_buffer v;
1616 DBG("PlanB: IOCTL VIDIOCSFBUF\n");
1618 if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
1620 if (copy_from_user(&v, arg, sizeof(v)))
1624 /* xawtv only asks for 8 bit in static grey, but
1625 * there is no way to know what it really means.. */
1627 fmt = VIDEO_PALETTE_GREY;
1630 fmt = VIDEO_PALETTE_RGB555;
1633 fmt = VIDEO_PALETTE_RGB32;
1635 /* We don't deliver these two... */
1642 if (palette2fmt[fmt].bpp * v.width > v.bytesperline) {
1646 pb->win.bpp = palette2fmt[fmt].bpp;
1647 pb->win.color_fmt = fmt;
1648 pb->fb.phys = (unsigned long) v.base;
1649 pb->win.sheight = v.height;
1650 pb->win.swidth = v.width;
1651 pb->picture.depth = pb->win.depth = v.depth;
1652 pb->win.bpl = pb->win.bpp * pb->win.swidth;
1653 pb->win.pad = v.bytesperline - pb->win.bpl;
1655 DBG("PlanB: Display at %p is %d by %d, bytedepth %d,"
1656 " bpl %d (+ %d)\n", v.base, v.width,v.height,
1657 pb->win.bpp, pb->win.bpl, pb->win.pad);
1659 pb->cmd_buff_inited = 0;
1661 suspend_overlay(pb);
1670 struct video_buffer v;
1672 DBG("PlanB: IOCTL VIDIOCGFBUF\n");
1674 v.base = (void *)pb->fb.phys;
1675 v.height = pb->win.sheight;
1676 v.width = pb->win.swidth;
1677 v.depth = pb->win.depth;
1678 v.bytesperline = pb->win.bpl + pb->win.pad;
1679 if (copy_to_user(arg, &v, sizeof(v)))
1687 if(copy_from_user(&i, arg, sizeof(i)))
1690 DBG("PlanB: IOCTL VIDIOCCAPTURE Stop\n");
1699 DBG("PlanB: IOCTL VIDIOCCAPTURE Start\n");
1701 if (pb->fb.phys == 0 ||
1702 pb->win.width == 0 ||
1703 pb->win.height == 0)
1709 if(!(pb->cmd_buff_inited))
1718 struct video_channel v;
1720 DBG("PlanB: IOCTL VIDIOCGCHAN\n");
1722 if(copy_from_user(&v, arg,sizeof(v)))
1726 v.type = VIDEO_TYPE_CAMERA;
1727 v.norm = pb->win.norm;
1731 strcpy(v.name,"Composite");
1734 strcpy(v.name,"SVHS");
1740 if(copy_to_user(arg,&v,sizeof(v)))
1747 struct video_channel v;
1749 DBG("PlanB: IOCTL VIDIOCSCHAN\n");
1751 if(copy_from_user(&v, arg, sizeof(v)))
1754 if (v.norm != pb->win.norm) {
1759 case VIDEO_MODE_PAL:
1760 case VIDEO_MODE_SECAM:
1761 maxlines = PLANB_MAXLINES;
1763 case VIDEO_MODE_NTSC:
1764 maxlines = PLANB_NTSC_MAXLINES;
1767 DBG(" invalid norm %d.\n", v.norm);
1772 /* empty the grabbing queue */
1774 interruptible_sleep_on(&pb->capq);
1775 pb->maxlines = maxlines;
1776 pb->win.norm = v.norm;
1777 /* Stop overlay if running */
1778 suspend_overlay(pb);
1779 for(i = 0; i < MAX_GBUFFERS; i++)
1780 pb->gbuf[i].norm_switch = 1;
1781 /* I know it's an overkill, but.... */
1783 /* ok, now init it accordingly */
1785 /* restart overlay if it was running */
1792 case 0: /* Composite */
1793 saa_set (SAA7196_IOCC,
1794 ((saa_regs[pb->win.norm][SAA7196_IOCC] &
1798 saa_set (SAA7196_IOCC,
1799 ((saa_regs[pb->win.norm][SAA7196_IOCC] &
1803 DBG(" invalid channel %d.\n", v.channel);
1812 struct video_picture vp = pb->picture;
1814 DBG("PlanB: IOCTL VIDIOCGPICT\n");
1816 vp.palette = pb->win.color_fmt;
1817 if(copy_to_user(arg,&vp,sizeof(vp)))
1823 struct video_picture vp;
1825 DBG("PlanB: IOCTL VIDIOCSPICT\n");
1827 if(copy_from_user(&vp,arg,sizeof(vp)))
1830 /* Should we do sanity checks here? */
1832 saa_set (SAA7196_BRIG, (unsigned char)
1833 ((pb->picture.brightness) >> 8), pb);
1834 saa_set (SAA7196_HUEC, (unsigned char)
1835 ((pb->picture.hue) >> 8) ^ 0x80, pb);
1836 saa_set (SAA7196_CSAT, (unsigned char)
1837 ((pb->picture.colour) >> 9), pb);
1838 saa_set (SAA7196_CONT, (unsigned char)
1839 ((pb->picture.contrast) >> 9), pb);
1846 struct video_window vw;
1847 struct video_clip clip;
1850 DBG("PlanB: IOCTL VIDIOCSWIN\n");
1852 if(copy_from_user(&vw,arg,sizeof(vw)))
1856 /* Stop overlay if running */
1857 suspend_overlay(pb);
1858 pb->win.interlace = (vw.height > pb->maxlines/2)? 1: 0;
1859 if (pb->win.x != vw.x ||
1860 pb->win.y != vw.y ||
1861 pb->win.width != vw.width ||
1862 pb->win.height != vw.height ||
1863 !pb->cmd_buff_inited) {
1866 pb->win.width = vw.width;
1867 pb->win.height = vw.height;
1870 DBG("PlanB: Window at (%d,%d) size %dx%d\n", vw.x, vw.y, vw.width,
1873 /* Reset clip mask */
1874 memset ((void *) pb->mask, 0xff, (pb->maxlines
1875 * ((PLANB_MAXPIXELS + 7) & ~7)) / 8);
1876 /* Add any clip rects */
1877 for (i = 0; i < vw.clipcount; i++) {
1878 if (copy_from_user(&clip, vw.clips + i,
1879 sizeof(struct video_clip)))
1881 add_clip(pb, &clip);
1883 /* restart overlay if it was running */
1890 struct video_window vw;
1892 DBG("PlanB: IOCTL VIDIOCGWIN\n");
1896 vw.width=pb->win.width;
1897 vw.height=pb->win.height;
1900 if(pb->win.interlace)
1901 vw.flags|=VIDEO_WINDOW_INTERLACE;
1902 if(copy_to_user(arg,&vw,sizeof(vw)))
1910 DBG("PlanB: IOCTL VIDIOCSYNC\n");
1912 if(copy_from_user((void *)&i,arg,sizeof(int)))
1915 DBG("PlanB: sync to frame %d\n", i);
1917 if(i > (MAX_GBUFFERS - 1) || i < 0)
1919 gbuf = &pb->gbuf[i];
1921 switch (*gbuf->status) {
1922 case GBUFFER_UNUSED:
1924 case GBUFFER_GRABBING:
1925 DBG("PlanB: waiting for grab"
1927 interruptible_sleep_on(&pb->capq);
1928 if(signal_pending(current))
1932 *gbuf->status = GBUFFER_UNUSED;
1938 case VIDIOCMCAPTURE:
1940 struct video_mmap vm;
1943 DBG("PlanB: IOCTL VIDIOCMCAPTURE\n");
1945 if(copy_from_user((void *) &vm,(void *)arg,sizeof(vm)))
1948 if(fr > (MAX_GBUFFERS - 1) || fr < 0)
1950 if (*pb->gbuf[fr].status != GBUFFER_UNUSED)
1953 return vgrab(pb, &vm);
1959 struct video_mbuf vm;
1961 DBG("PlanB: IOCTL VIDIOCGMBUF\n");
1963 memset(&vm, 0 , sizeof(vm));
1964 vm.size = PLANB_MAX_FBUF * MAX_GBUFFERS;
1965 vm.frames = MAX_GBUFFERS;
1966 for(i = 0; i<MAX_GBUFFERS; i++)
1967 vm.offsets[i] = PLANB_MAX_FBUF * i;
1968 if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
1975 struct video_unit vu;
1977 DBG("PlanB: IOCTL VIDIOCGUNIT\n");
1979 vu.video=pb->video_dev.minor;
1980 vu.vbi=pb->vbi_dev.minor;
1981 vu.radio=VIDEO_NO_UNIT;
1982 vu.audio=VIDEO_NO_UNIT;
1983 vu.teletext=VIDEO_NO_UNIT;
1984 if(copy_to_user((void *)arg, (void *)&vu, sizeof(vu)))
1989 case PLANBIOCGSAAREGS:
1991 struct planb_saa_regs preg;
1993 DBG("PlanB: IOCTL PLANBIOCGSAAREGS\n");
1995 if(copy_from_user(&preg, arg, sizeof(preg)))
1997 if(preg.addr >= SAA7196_NUMREGS)
1999 preg.val = saa_regs[pb->win.norm][preg.addr];
2000 if(copy_to_user((void *)arg, (void *)&preg,
2006 case PLANBIOCSSAAREGS:
2008 struct planb_saa_regs preg;
2010 DBG("PlanB: IOCTL PLANBIOCSSAAREGS\n");
2012 if(copy_from_user(&preg, arg, sizeof(preg)))
2014 if(preg.addr >= SAA7196_NUMREGS)
2016 saa_set (preg.addr, preg.val, pb);
2022 struct planb_stat_regs pstat;
2024 DBG("PlanB: IOCTL PLANBIOCGSTAT\n");
2026 pstat.ch1_stat = readl(&pb->planb_base->ch1.status);
2027 pstat.ch2_stat = readl(&pb->planb_base->ch2.status);
2028 pstat.ch1_cmdbase = (unsigned long)pb->vid_cbo.start;
2029 pstat.ch2_cmdbase = (unsigned long)pb->clip_cbo.start;
2030 pstat.ch1_cmdptr = readl(&pb->planb_base->ch1.cmdptr);
2031 pstat.ch2_cmdptr = readl(&pb->planb_base->ch2.cmdptr);
2032 pstat.saa_stat0 = saa_status(0, pb);
2033 pstat.saa_stat1 = saa_status(1, pb);
2035 if(copy_to_user((void *)arg, (void *)&pstat,
2041 case PLANBIOCSMODE: {
2044 DBG("PlanB: IOCTL PLANBIOCSMODE\n");
2046 if(copy_from_user(&v, arg, sizeof(v)))
2052 saa_set (SAA7196_STDC,
2053 (saa_regs[pb->win.norm][SAA7196_STDC] &
2056 case PLANB_VTR_MODE:
2057 saa_set (SAA7196_STDC,
2058 (saa_regs[pb->win.norm][SAA7196_STDC] |
2068 case PLANBIOCGMODE: {
2071 DBG("PlanB: IOCTL PLANBIOCGMODE\n");
2073 if(copy_to_user(arg,&v,sizeof(v)))
2077 #ifdef PLANB_GSCANLINE
2078 case PLANBG_GRAB_BPL: {
2079 int v=pb->gbytes_per_line;
2081 DBG("PlanB: IOCTL PLANBG_GRAB_BPL\n");
2083 if(copy_to_user(arg,&v,sizeof(v)))
2087 #endif /* PLANB_GSCANLINE */
2089 /* These serve only for debugging... */
2091 case PLANB_INTR_DEBUG: {
2094 DBG("PlanB: IOCTL PLANB_INTR_DEBUG\n");
2096 if(copy_from_user(&i, arg, sizeof(i)))
2099 /* avoid hang ups all together */
2100 for (i = 0; i < MAX_GBUFFERS; i++) {
2101 if(*pb->gbuf[i].status == GBUFFER_GRABBING) {
2102 *pb->gbuf[i].status = GBUFFER_DONE;
2107 wake_up_interruptible(&pb->capq);
2110 case PLANB_INV_REGS: {
2112 struct planb_any_regs any;
2114 DBG("PlanB: IOCTL PLANB_INV_REGS\n");
2116 if(copy_from_user(&any, arg, sizeof(any)))
2118 if(any.offset < 0 || any.offset + any.bytes > 0x400)
2122 for (i = 0; i < any.bytes; i++) {
2124 readb((unsigned char *)pb->planb_base
2127 if(copy_to_user(arg,&any,sizeof(any)))
2131 case PLANBIOCGDBDMABUF:
2133 struct planb_buf_regs buf;
2137 DBG("PlanB: IOCTL PLANBIOCGDBDMABUF\n");
2139 if(copy_from_user(&buf, arg, sizeof(buf)))
2142 if( (buf.start < 0) || (buf.end < 0x10) ||
2143 (buf.end < buf.start+0x10) ||
2144 (buf.end > 2*pb->tab_size) )
2147 printk ("PlanB DBDMA command buffer:\n");
2148 for (i=(buf.start>>4); i<=(buf.end>>4); i++) {
2149 printk(" 0x%04x:", i<<4);
2150 dc = pb->vid_cbo.start + i;
2151 printk (" %04x %04x %08x %08x %04x %04x\n",
2152 dc->req_count, dc->command, dc->phy_addr,
2153 dc->cmd_dep, dc->res_count, dc->xfer_status);
2161 DBG("PlanB: Unimplemented IOCTL: %d (0x%x)\n", cmd, cmd);
2162 return -ENOIOCTLCMD;
2164 /* Some IOCTLs are currently unsupported on PlanB */
2165 case VIDIOCGTUNER: {
2166 DBG("PlanB: IOCTL VIDIOCGTUNER\n");
2167 goto unimplemented; }
2168 case VIDIOCSTUNER: {
2169 DBG("PlanB: IOCTL VIDIOCSTUNER\n");
2170 goto unimplemented; }
2172 DBG("PlanB: IOCTL VIDIOCSFREQ\n");
2173 goto unimplemented; }
2175 DBG("PlanB: IOCTL VIDIOCGFREQ\n");
2176 goto unimplemented; }
2178 DBG("PlanB: IOCTL VIDIOCKEY\n");
2179 goto unimplemented; }
2180 case VIDIOCSAUDIO: {
2181 DBG("PlanB: IOCTL VIDIOCSAUDIO\n");
2182 goto unimplemented; }
2183 case VIDIOCGAUDIO: {
2184 DBG("PlanB: IOCTL VIDIOCGAUDIO\n");
2185 goto unimplemented; }
2187 DBG(" Unimplemented\n");
2188 return -ENOIOCTLCMD;
2193 static int planb_mmap(struct video_device *dev, const char *adr, unsigned long size)
2195 struct planb *pb = (struct planb *)dev->priv;
2196 unsigned long start = (unsigned long)adr;
2199 if (size > MAX_GBUFFERS * PLANB_MAX_FBUF)
2203 if((err=grabbuf_alloc(pb)))
2206 for (i = 0; i < pb->rawbuf_nchunks; i++) {
2207 if (remap_page_range(start, virt_to_phys((void *)pb->rawbuf[i]),
2208 PAGE_SIZE, PAGE_SHARED))
2211 if (size <= PAGE_SIZE)
2218 /**********************************
2219 * VBI device operation functions *
2220 **********************************/
2222 static long planb_vbi_read(struct video_device *dev, char *buf,
2223 unsigned long count, int nonblock)
2225 struct planb *pb = (struct planb *)dev->priv;
2227 DECLARE_WAITQUEUE(wait, current);
2230 printk ("PlanB: VBI read %li bytes.\n", count);
2234 while (todo && todo>(q=VBIBUF_SIZE-pb->vbip))
2236 if(copy_to_user((void *) buf, (void *) pb->vbibuf+pb->vbip, q))
2241 add_wait_queue(&pb->vbiq, &wait);
2242 current->state = TASK_INTERRUPTIBLE;
2243 if (todo && q==VBIBUF_SIZE-pb->vbip) {
2245 remove_wait_queue(&pb->vbiq, &wait);
2246 current->state = TASK_RUNNING;
2248 return -EWOULDBLOCK;
2252 if(signal_pending(current)) {
2253 remove_wait_queue(&pb->vbiq, &wait);
2254 current->state = TASK_RUNNING;
2261 remove_wait_queue(&pb->vbiq, &wait);
2262 current->state = TASK_RUNNING;
2265 if(copy_to_user((void *) buf, (void *) pb->vbibuf+pb->vbip,
2273 static unsigned int planb_vbi_poll(struct video_device *dev,
2274 struct file *file, poll_table *wait)
2276 struct planb *pb = (struct planb *)dev->priv;
2277 unsigned int mask = 0;
2279 printk ("PlanB: VBI poll.\n");
2280 poll_wait(file, &pb->vbiq, wait);
2282 if (pb->vbip < VBIBUF_SIZE)
2283 mask |= (POLLIN | POLLRDNORM);
2288 static int planb_vbi_open(struct video_device *dev, int flags)
2290 struct planb *pb = (struct planb *)dev->priv;
2293 /* first open on the driver? */
2294 if(pb->vid_user + pb->vbi_user == 0) {
2295 if((err = planb_prepare_open(pb)) != 0)
2298 /* first open on the vbi device? */
2299 if(pb->vbi_user == 1) {
2300 if((err = planb_prepare_vbi(pb)) != 0)
2305 DBG("PlanB: VBI open\n");
2311 static void planb_vbi_close(struct video_device *dev)
2313 struct planb *pb = (struct planb *)dev->priv;
2315 /* last close on vbi device? */
2316 if(--pb->vbi_user == 0) {
2317 planb_close_vbi(pb);
2319 /* last close on any planb device? */
2320 if(pb->vid_user + pb->vbi_user == 0) {
2321 planb_prepare_close(pb);
2324 DBG("PlanB: VBI close\n");
2330 static int planb_vbi_ioctl(struct video_device *dev, unsigned int cmd,
2334 /* This is only for alevt */
2336 DBG("PlanB: IOCTL BTTV_VBISIZE.\n");
2339 DBG("PlanB: Unimplemented VBI IOCTL no. %i.\n", cmd);
2344 static struct video_device planb_template=
2347 name: PLANB_DEVICE_NAME,
2348 type: VID_TYPE_CAPTURE|VID_TYPE_OVERLAY,
2349 hardware: VID_HARDWARE_PLANB,
2353 write: planb_write, /* not implemented */
2355 mmap: planb_mmap, /* mmap? */
2358 static struct video_device planb_vbi_template=
2361 name: PLANB_VBI_NAME,
2362 type: VID_TYPE_CAPTURE|VID_TYPE_TELETEXT,
2363 hardware: VID_HARDWARE_PLANB,
2364 open: planb_vbi_open,
2365 close: planb_vbi_close,
2366 read: planb_vbi_read,
2367 write: planb_write, /* not implemented */
2368 poll: planb_vbi_poll,
2369 ioctl: planb_vbi_ioctl,
2372 static int __devinit init_planb(struct planb *pb)
2374 unsigned char saa_rev;
2376 unsigned long flags;
2378 printk(KERN_INFO "PlanB: PowerMacintosh video input driver rev. %s\n", PLANB_REV);
2380 pb->video_dev.minor = -1;
2383 /* Simple sanity check */
2384 if(def_norm >= NUM_SUPPORTED_NORM || def_norm < 0) {
2385 printk(KERN_ERR "PlanB: Option(s) invalid\n");
2388 memset ((void *) &pb->win, 0, sizeof (struct planb_window));
2389 pb->win.norm = def_norm;
2390 pb->win.mode = PLANB_TV_MODE; /* TV mode */
2391 pb->win.interlace = 1;
2394 pb->win.width = 768; /* 640 */
2395 pb->win.height = 576; /* 480 */
2399 pb->win.color_fmt = VIDEO_PALETTE_RGB32;
2400 pb->win.bpl = 1024 * pb->win.bpp;
2401 pb->win.swidth = 1024;
2402 pb->win.sheight = 768;
2404 #ifdef PLANB_GSCANLINE
2405 if((pb->gbytes_per_line = PLANB_MAXPIXELS * 4) > PAGE_SIZE
2406 || (pb->gbytes_per_line <= 0))
2409 /* page align pb->gbytes_per_line for DMA purpose */
2410 for(i = PAGE_SIZE; pb->gbytes_per_line < (i >> 1);)
2412 pb->gbytes_per_line = i;
2415 pb->tab_size = PLANB_MAXLINES + 40;
2417 init_MUTEX(&pb->lock);
2418 pb->vid_cbo.start = 0;
2419 pb->clip_cbo.start = 0;
2423 init_waitqueue_head(&pb->suspendq);
2424 pb->cmd_buff_inited = 0;
2429 pb->vbi_dev.minor = -1;
2434 init_waitqueue_head(&pb->vbiq);
2436 /* Reset DMA controllers */
2437 planb_dbdma_stop(&pb->planb_base->ch2);
2438 planb_dbdma_stop(&pb->planb_base->ch1);
2440 saa_rev = (saa_status(0, pb) & 0xf0) >> 4;
2441 printk(KERN_INFO "PlanB: SAA7196 video processor rev. %d\n", saa_rev);
2442 /* Initialize the SAA registers in memory and on chip */
2445 /* clear interrupt mask */
2446 pb->intr_mask = PLANB_CLR_IRQ;
2448 save_flags(flags); cli();
2449 result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb);
2451 if (result==-EINVAL)
2452 printk(KERN_ERR "PlanB: Bad irq number (%d) "
2453 "or handler\n", (int)pb->irq);
2454 else if (result==-EBUSY)
2455 printk(KERN_ERR "PlanB: I don't know why, "
2456 "but IRQ %d is busy\n", (int)pb->irq);
2457 restore_flags(flags);
2460 disable_irq(pb->irq);
2461 restore_flags(flags);
2463 pb->picture.brightness=0x90<<8;
2464 pb->picture.contrast = 0x70 << 8;
2465 pb->picture.colour = 0x70<<8;
2466 pb->picture.hue = 0x8000;
2467 pb->picture.whiteness = 0;
2468 pb->picture.depth = pb->win.depth;
2470 init_waitqueue_head(&pb->capq);
2471 for(i=0; i<MAX_GBUFFERS; i++) {
2472 gbuf_ptr gbuf = &pb->gbuf[i];
2474 gbuf->idx = PLANB_MAX_FBUF * i / PAGE_SIZE;
2479 #ifndef PLANB_GSCANLINE
2480 gbuf->l_fr_addr_idx = MAX_GBUFFERS * (PLANB_MAX_FBUF
2481 / PAGE_SIZE + 1) + MAX_LNUM * i;
2489 /* enable interrupts */
2490 writel(PLANB_CLR_IRQ, &pb->planb_base->intr_stat);
2491 pb->intr_mask = PLANB_FRM_IRQ;
2492 enable_irq(pb->irq);
2494 /* Now add the templates and register the device units. */
2495 memcpy(&pb->video_dev,&planb_template,sizeof(planb_template));
2496 pb->video_dev.priv = pb;
2497 memcpy(&pb->vbi_dev,&planb_vbi_template,sizeof(planb_vbi_template));
2499 if(video_register_device(&pb->video_dev, VFL_TYPE_GRABBER, video_nr)<0)
2501 if(video_register_device(&pb->vbi_dev, VFL_TYPE_VBI, vbi_nr)<0) {
2502 video_unregister_device(&pb->video_dev);
2510 * Scan for a PlanB controller and map the io memory
2512 static int find_planb(void)
2515 struct pci_dev *pdev = NULL;
2519 if (_machine != _MACH_Pmac)
2522 pdev = pci_find_device(APPLE_VENDOR_ID, PLANB_DEV_ID, pdev);
2524 printk(KERN_WARNING "PlanB: no device found!\n");
2530 base = pdev->resource[0].start;
2532 DBG("PlanB: Found device %s, membase 0x%lx, irq %d\n",
2533 pdev->slot_name, base, pdev->irq);
2535 /* Enable response in memory space, bus mastering,
2536 use memory write and invalidate */
2537 pci_enable_device (pdev);
2538 pci_set_master (pdev);
2540 /* value copied from MacOS... */
2541 pci_write_config_byte (pdev, PCI_LATENCY_TIMER, 0x40);
2543 planb_regs = (volatile struct planb_registers *)
2544 ioremap (base, 0x400);
2545 pb->planb_base = planb_regs;
2546 pb->planb_base_bus = (struct planb_registers *)base;
2547 pb->irq = pdev->irq;
2552 static void release_planb(void)
2558 /* stop and flush DMAs unconditionally */
2559 planb_dbdma_stop(&pb->planb_base->ch2);
2560 planb_dbdma_stop(&pb->planb_base->ch1);
2562 /* clear and free interrupts */
2563 pb->intr_mask = PLANB_CLR_IRQ;
2564 writel(PLANB_CLR_IRQ, &pb->planb_base->intr_stat);
2565 free_irq(pb->irq, pb);
2567 /* make sure all allocated memory are freed */
2568 planb_prepare_close(pb);
2570 printk(KERN_INFO "PlanB: unregistering with v4l\n");
2571 video_unregister_device(&pb->video_dev);
2572 video_unregister_device(&pb->vbi_dev);
2574 /* note that iounmap() does nothing on the PPC right now */
2575 iounmap ((void *)pb->planb_base);
2578 static int __init init_planbs(void)
2582 planb_num=find_planb();
2589 if (init_planb(&planbs) < 0) {
2590 printk(KERN_ERR "PlanB: error registering planb device"
2598 static void __exit exit_planbs(void)
2603 module_init(init_planbs);
2604 module_exit(exit_planbs);