OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [media/] [video/] [planb.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
    planb - v4l-compatible frame grabber driver for the PlanB hardware
3
 
4
    PlanB is used in the 7x00/8x00 series of PowerMacintosh
5
    Computers as video input DMA controller.
6
 
7
    Copyright (C) 1998 - 2002  Michel Lanners <mailto:mlan@cpu.lu>
8
 
9
    Based largely on the old bttv driver by Ralph Metzler
10
 
11
    Additional debugging and coding by Takashi Oe <mailto:toe@unlserve.unl.edu>
12
 
13
    For more information, see <http://www.cpu.lu/~mlan/planb.html>
14
 
15
 
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.
20
 
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.
25
 
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.
29
*/
30
 
31
/* $Id: planb.c,v 1.1.1.1 2004-04-15 02:19:41 phoenix Exp $ */
32
 
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>
44
#include <linux/mm.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>
51
#include <asm/io.h>
52
#include <asm/prom.h>
53
#include <asm/dbdma.h>
54
#include <asm/pgtable.h>
55
#include <asm/page.h>
56
#include <asm/irq.h>
57
#include <asm/semaphore.h>
58
 
59
/* Define these to get general / interrupt debugging */
60
#undef DEBUG
61
#undef IDEBUG
62
 
63
//#define DEBUG
64
 
65
#ifdef DEBUG
66
#define DBG(x...) printk(KERN_DEBUG ## x)
67
#else
68
#define DBG(x...)
69
#endif
70
#ifdef IDEBUG
71
#define IDBG(x...) printk(KERN_DEBUG ## x)
72
#else
73
#define IDBG(x...)
74
#endif
75
 
76
#include "planb.h"
77
#include "saa7196.h"
78
 
79
static struct planb planbs;
80
static volatile struct planb_registers *planb_regs;
81
 
82
static int def_norm = PLANB_DEF_NORM;   /* default norm */
83
static int video_nr = -1;
84
static int vbi_nr = -1;
85
 
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");
90
 
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");
94
 
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 *,
107
        poll_table *);
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);
112
 
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,
140
        struct planb *);
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 *);
145
 
146
/*******************************/
147
/* Memory management functions */
148
/*******************************/
149
 
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
153
 * patches.
154
 *
155
 *                                      Michel Lanners (mlan@cpu.lu)
156
 */
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
162
 * pages for DMA....
163
 */
164
static int grabbuf_alloc(struct planb *pb)
165
{
166
        int i, npage;
167
 
168
        npage = MAX_GBUFFERS * ((PLANB_MAX_FBUF / PAGE_SIZE + 1)
169
#ifndef PLANB_GSCANLINE
170
                + MAX_LNUM
171
#endif /* PLANB_GSCANLINE */
172
                );
173
        if ((pb->rawbuf = (unsigned char**) kmalloc (npage
174
                                * sizeof(unsigned long), GFP_KERNEL)) == 0)
175
                return -ENOMEM;
176
        for (i = 0; i < npage; i++) {
177
                pb->rawbuf[i] = (unsigned char *)__get_free_pages(GFP_KERNEL |
178
                                                                GFP_DMA, 0);
179
                if (!pb->rawbuf[i])
180
                        break;
181
                mem_map_reserve(virt_to_page(pb->rawbuf[i]));
182
        }
183
        if (i-- < npage) {
184
                DBG("PlanB: init_grab: grab buffer not allocated\n");
185
                for (; i > 0; i--) {
186
                        mem_map_unreserve(virt_to_page(pb->rawbuf[i]));
187
                        free_pages((unsigned long)pb->rawbuf[i], 0);
188
                }
189
                kfree(pb->rawbuf);
190
                return -ENOBUFS;
191
        }
192
        pb->rawbuf_nchunks = npage;
193
        return 0;
194
}
195
 
196
/*****************************/
197
/* Hardware access functions */
198
/*****************************/
199
 
200
static void saa_write_reg(unsigned char addr, unsigned char val)
201
{
202
        planb_regs->saa_addr = addr; eieio();
203
        planb_regs->saa_regval = val; eieio();
204
        return;
205
}
206
 
207
/* return  status byte 0 or 1: */
208
static unsigned char saa_status(int byte, struct planb *pb)
209
{
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]);
213
 
214
        /* Let's wait 30msec for this one */
215
        current->state = TASK_INTERRUPTIBLE;
216
        schedule_timeout(30 * HZ / 1000);
217
 
218
        return (unsigned char)in_8 (&planb_regs->saa_status);
219
}
220
 
221
static void saa_set(unsigned char addr, unsigned char val, struct planb *pb)
222
{
223
        if(saa_regs[pb->win.norm][addr] != val) {
224
                saa_regs[pb->win.norm][addr] = val;
225
                saa_write_reg (addr, val);
226
        }
227
        return;
228
}
229
 
230
static void saa_init_regs(struct planb *pb)
231
{
232
        int i;
233
 
234
        for (i = 0; i < SAA7196_NUMREGS; i++)
235
                saa_write_reg (i, saa_regs[pb->win.norm][i]);
236
}
237
 
238
static void saa_geo_setup(int width, int height, int interlace,
239
        int fmt, struct planb *pb)
240
{
241
        int ht, norm = pb->win.norm;
242
 
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);
246
 
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)
253
                                                | (ht >> 8 & 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);
263
}
264
 
265
/***************************/
266
/* DBDMA support functions */
267
/***************************/
268
 
269
static inline void planb_dbdma_restart(dbdma_regs_ptr ch)
270
{
271
        writel(PLANB_CLR(RUN), &ch->control);
272
        writel(PLANB_SET(RUN|WAKE) | PLANB_CLR(PAUSE), &ch->control);
273
}
274
 
275
static inline void planb_dbdma_stop(dbdma_regs_ptr ch)
276
{
277
        int i = 0;
278
 
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");
282
                i++;
283
        }
284
}
285
 
286
static inline void tab_cmd_dbdma(dbdma_cmd_ptr ch, unsigned short command,
287
        unsigned int cmd_dep)
288
{
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);
295
}
296
 
297
static inline void tab_cmd_store(dbdma_cmd_ptr ch, unsigned int phy_addr,
298
        unsigned int cmd_dep)
299
{
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);
305
}
306
 
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)
309
{
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);
315
}
316
 
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)
319
{
320
        int norm = pb->win.norm;
321
 
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),
326
                                                                SAA7196_FMTS);
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),
330
                                                                SAA7196_DPATH);
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),
338
                                                                SAA7196_OUTPIX);
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),
342
                                                                SAA7196_HFILT);
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),
346
                                                        SAA7196_OUTLINE);
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),
350
                                                                SAA7196_VYP);
351
        tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->saa_regval),
352
                                                saa_regs[norm][SAA7196_VYP]);
353
        return c1;
354
}
355
 
356
/******************************/
357
/* misc. supporting functions */
358
/******************************/
359
 
360
static inline void planb_lock(struct planb *pb)
361
{
362
        DBG("PlanB: planb_lock\n");
363
        down(&pb->lock);
364
}
365
 
366
static inline void planb_unlock(struct planb *pb)
367
{
368
        DBG("PlanB: planb_unlock\n");
369
        up(&pb->lock);
370
}
371
 
372
/***************/
373
/* Driver Core */
374
/***************/
375
 
376
/* number of entries in the circular DBDMA command buffer
377
 * initial stop, odd/even vbi, odd/even video, branch back */
378
#define NUMJUMPS 6
379
static int planb_prepare_open(struct planb *pb)
380
{
381
        dbdma_cmd_ptr   c;
382
        int             size, i;
383
 
384
        size = (NUMJUMPS + 1) * sizeof(struct dbdma_cmd);
385
 
386
        if((pb->jump_raw = kmalloc (size, GFP_KERNEL|GFP_DMA)) == 0)
387
                return -ENOMEM;
388
        memset(pb->jump_raw, 0, size);
389
        c = pb->jumpbuf = (dbdma_cmd_ptr) DBDMA_ALIGN (pb->jump_raw);
390
 
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);
397
 
398
        DBG("PlanB: planb_prepare_open, jumpbuffer at 0x%08x, length %d.\n",
399
                (unsigned int)pb->jumpbuf, size);
400
        return 0;
401
}
402
 
403
#define VBIDUMMY 40     /* must be even !! */
404
static int planb_prepare_vbi(struct planb *pb)
405
{
406
        int     size;
407
 
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);
411
 
412
        if ((pb->vbi_raw = kmalloc (size, GFP_KERNEL|GFP_DMA)) == 0)
413
                return -ENOMEM;
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;
421
 
422
        DBG("PlanB: planb_prepare_vbi, dbdma cmd_buf at 0x%08x, length %d.\n",
423
                (unsigned int)pb->vbi_cbo.start, 2*size);
424
        return 0;
425
}
426
 
427
static int planb_prepare_video(struct planb *pb)
428
{
429
        int     i, size;
430
 
431
        /* FIXME: This is stressing kmalloc to its limits...
432
                  We really should allocate smaller chunks. */
433
 
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)
442
                return -ENOMEM;
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;
464
        }
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);
470
 
471
        pb->rawbuf = NULL;
472
        pb->rawbuf_nchunks = 0;
473
        pb->grabbing = 0;
474
        for (i = 0; i < MAX_GBUFFERS; i++) {
475
                gbuf_ptr        gbuf = &pb->gbuf[i];
476
 
477
                *gbuf->status = GBUFFER_UNUSED;
478
                gbuf->width = 0;
479
                gbuf->height = 0;
480
                gbuf->fmt = 0;
481
                gbuf->norm_switch = 0;
482
#ifndef PLANB_GSCANLINE
483
                gbuf->lsize = 0;
484
                gbuf->lnum = 0;
485
#endif
486
        }
487
        pb->gcount = 0;
488
        pb->suspend = 0;
489
        pb->last_fr = -999;
490
        pb->prev_last_fr = -999;
491
 
492
        /* Reset DMA controllers */
493
        planb_dbdma_stop(&pb->planb_base->ch2);
494
        planb_dbdma_stop(&pb->planb_base->ch1);
495
 
496
        DBG("PlanB: planb_prepare_video, dbdma cmd_buf at 0x%08x, "
497
                "length %d.\n", (unsigned int)pb->vid_cbo.start, 2*size);
498
        return 0;
499
}
500
 
501
static void planb_prepare_close(struct planb *pb)
502
{
503
        /* make sure the dma's are idle */
504
        planb_dbdma_stop(&pb->planb_base->ch2);
505
        planb_dbdma_stop(&pb->planb_base->ch1);
506
 
507
        if(pb->jump_raw != 0) {
508
                kfree(pb->jump_raw);
509
                pb->jump_raw = 0;
510
        }
511
        return;
512
}
513
 
514
static void planb_close_vbi(struct planb *pb)
515
{
516
        /* FIXME: stop running DMA */
517
 
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);
521
 
522
        if(pb->vbi_raw != 0) {
523
                kfree (pb->vbi_raw);
524
                pb->vbi_raw = 0;
525
        }
526
 
527
        /* FIXME: deallocate VBI data buffer */
528
 
529
        /* FIXME: restart running DMA if app. */
530
        return;
531
}
532
 
533
static void planb_close_video(struct planb *pb)
534
{
535
        int i;
536
 
537
        /* FIXME: stop running DMA */
538
 
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  */
543
#if 0
544
        tab_cmd_dbdma(pb->clip_cbo.jumpaddr, DBDMA_NOP, 0);
545
        tab_cmd_dbdma(pb->clip_cbe.jumpaddr, DBDMA_NOP, 0);
546
#endif
547
 
548
        if(pb->vid_raw != 0) {
549
                kfree (pb->vid_raw);
550
                pb->vid_raw = 0;
551
                pb->cmd_buff_inited = 0;
552
        }
553
        if(pb->rawbuf) {
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);
557
                }
558
                kfree(pb->rawbuf);
559
        }
560
        pb->rawbuf = NULL;
561
 
562
        /* FIXME: restart running DMA if app. */
563
        return;
564
}
565
 
566
/*****************************/
567
/* overlay support functions */
568
/*****************************/
569
 
570
static void overlay_start(struct planb *pb)
571
{
572
        DBG("PlanB: overlay_start()\n");
573
 
574
        if(ACTIVE & readl(&pb->planb_base->ch1.status)) {
575
 
576
                DBG("PlanB: presumably, grabbing is in progress...\n");
577
 
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);
584
                eieio();
585
                pb->prev_last_fr = pb->last_fr;
586
                pb->last_fr = -2;
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);
593
                }
594
        } else {
595
 
596
                DBG("PlanB: currently idle, so can do whatever\n");
597
 
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);
605
                pb->last_fr = -1;
606
        }
607
        return;
608
}
609
 
610
static void overlay_stop(struct planb *pb)
611
{
612
        DBG("PlanB: overlay_stop()\n");
613
 
614
        if(pb->last_fr == -1) {
615
 
616
                DBG("PlanB: no grabbing, it seems...\n");
617
 
618
                planb_dbdma_stop(&pb->planb_base->ch2);
619
                planb_dbdma_stop(&pb->planb_base->ch1);
620
                pb->last_fr = -999;
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);
624
                eieio();
625
                cmd_dep = (unsigned int)readl(&pb->overlay_last1->cmd_dep);
626
                if(overlay_is_active(pb)) {
627
 
628
                        DBG("PlanB: overlay is currently active\n");
629
 
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);
636
                        }
637
                }
638
                pb->last_fr = pb->prev_last_fr;
639
                pb->prev_last_fr = -999;
640
        }
641
        return;
642
}
643
 
644
static void suspend_overlay(struct planb *pb)
645
{
646
        int fr = -1;
647
        struct dbdma_cmd last;
648
 
649
        DBG("PlanB: suspend_overlay: %d\n", pb->suspend);
650
 
651
        if(pb->suspend++)
652
                return;
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);
658
                }
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));
665
                        return;
666
                }
667
        }
668
        pb->suspended.overlay = 0;
669
        pb->suspended.frame = fr;
670
        memcpy(&pb->suspended.cmd, &last, sizeof(last));
671
        return;
672
}
673
 
674
static void resume_overlay(struct planb *pb)
675
{
676
 
677
        DBG("PlanB: resume_overlay: %d\n", pb->suspend);
678
 
679
        if(pb->suspend > 1)
680
                return;
681
        if(pb->suspended.frame != -1) {
682
                memcpy((void*)pb->gbuf[pb->suspended.frame].last_cmd,
683
                        &pb->suspended.cmd, sizeof(pb->suspended.cmd));
684
        }
685
        if(ACTIVE & readl(&pb->planb_base->ch1.status)) {
686
                goto finish;
687
        }
688
        if(pb->suspended.overlay) {
689
 
690
                DBG("PlanB: overlay being resumed\n");
691
 
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);
709
        }
710
 
711
finish:
712
        pb->suspend--;
713
        wake_up_interruptible(&pb->suspendq);
714
}
715
 
716
static void add_clip(struct planb *pb, struct video_clip *clip)
717
{
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;
723
 
724
        DBG("PlanB: clip %dx%d+%d+%d\n", wc, hc, xc, yc);
725
 
726
        if(xc < 0) {
727
                wc += xc;
728
                xc = 0;
729
        }
730
        if(yc < 0) {
731
                hc += yc;
732
                yc = 0;
733
        }
734
        if(xc + wc > ww)
735
                wc = ww - xc;
736
        if(wc <= 0) /* Nothing to do */
737
                return;
738
        if(yc + hc > hw)
739
                hc = hw - yc;
740
 
741
        for (y = yc; y < yc+hc; y++) {
742
                xtmp1=xc>>3;
743
                xtmp2=(xc+wc)>>3;
744
                base = pb->mask + y*96;
745
                if(xc != 0 || wc >= 8)
746
                        *(base + xtmp1) &= (unsigned char)(0x00ff &
747
                                (0xff00 >> (xc&7)));
748
                for (x = xtmp1 + 1; x < xtmp2; x++) {
749
                        *(base + x) = 0;
750
                }
751
                if(xc < (ww & ~0x7))
752
                        *(base + xtmp2) &= (unsigned char)(0x00ff >>
753
                                ((xc+wc) & 7));
754
        }
755
 
756
        return;
757
}
758
 
759
static void fill_cmd_buff(struct planb *pb)
760
{
761
        int             restore = 0;
762
        dbdma_cmd_t     last;
763
 
764
        DBG("PlanB: fill_cmd_buff()\n");
765
 
766
        if(pb->overlay_last1 != pb->vid_cbo.start) {
767
                restore = 1;
768
                last = *(pb->overlay_last1);
769
        }
770
        memset ((void *) pb->vid_cbo.start, 0, 2 * pb->tab_size
771
                                        * sizeof(struct dbdma_cmd));
772
        cmd_buff (pb);
773
        if(restore)
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) {
778
                        int i;
779
 
780
                        DBG("PlanB: adjusting ch1's jump address\n");
781
 
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))
785
                                        goto found;
786
                                } else {
787
                                    if(jump_addr ==
788
                                            virt_to_bus(pb->gbuf[i].cap_cmd))
789
                                        goto found;
790
                                }
791
                        }
792
 
793
                        DBG("       not found!\n");
794
 
795
                        goto out;
796
found:
797
                        if(pb->gbuf[i].need_pre_capture)
798
                                writel(virt_to_bus(pb->overlay_last1),
799
                                        &pb->gbuf[i].pre_cmd->phy_addr);
800
                        else
801
                                writel(virt_to_bus(pb->overlay_last1),
802
                                        &pb->gbuf[i].cap_cmd->phy_addr);
803
                }
804
        }
805
out:
806
        pb->cmd_buff_inited = 1;
807
 
808
        return;
809
}
810
 
811
static void cmd_buff(struct planb *pb)
812
{
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;
817
 
818
        interlace = pb->win.interlace;
819
        bpp = pb->win.bpp;
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);
824
 
825
        /* Do video in: */
826
 
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),
848
                                                        PLANB_SET(CH_SYNC));
849
        tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),
850
                                                        PLANB_SET(DMA_ABORT));
851
 
852
        base = (pb->fb.phys + pb->fb.offset + pb->win.y * (pb->win.bpl +
853
                                        pb->win.pad) + pb->win.x * bpp);
854
 
855
        if (interlace) {
856
                stepsize = 2;
857
                jump = virt_to_bus(c1 + (nlines + 1) / 2);
858
        } else {
859
                stepsize = 1;
860
                jump = virt_to_bus(c1 + nlines);
861
        }
862
 
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);
867
 
868
        /* For non-interlaced, we use even fields only */
869
        if (!interlace)
870
                goto cmd_tab_data_end;
871
 
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),
883
                                                        PLANB_SET(CH_SYNC));
884
        tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->ch1.br_sel),
885
                                                        PLANB_SET(DMA_ABORT));
886
 
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);
892
 
893
        /* And jump back to the start */
894
cmd_tab_data_end:
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);
897
 
898
        /* Clipmask command buffer */
899
 
900
        /* Preamble commands: */
901
        tab_cmd_dbdma(c2++, DBDMA_NOP, 0);
902
        tab_cmd_store(c2++, (unsigned)(&pb->planb_base_bus->ch2.wait_sel),
903
                                                        PLANB_SET(CH_SYNC));
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),
908
                                                        PLANB_CLR(CH_SYNC));
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));
913
 
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);
920
 
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);
931
 
932
        /* For non-interlaced, we use only even fields */
933
        if(!interlace)
934
                goto cmd_tab_mask_end;
935
 
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);
945
 
946
        /* Inform channel 1 and jump back to start */
947
cmd_tab_mask_end:
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),
956
                                                        PLANB_CLR(RUN));
957
        tab_cmd_store(c2++, (unsigned)(&pb->planb_base_bus->ch1.control),
958
                                                        PLANB_SET(RUN));
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);
962
 
963
        eieio();
964
        return;
965
}
966
 
967
/*********************************/
968
/* grabdisplay support functions */
969
/*********************************/
970
 
971
static inline int overlay_is_active(struct planb *pb)
972
{
973
        unsigned int size = pb->tab_size * sizeof(struct dbdma_cmd);
974
        unsigned int caddr = (unsigned)readl(&pb->planb_base->ch1.cmdptr);
975
 
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);
979
}
980
 
981
static int vgrab(struct planb *pb, struct video_mmap *mp)
982
{
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];
987
 
988
        if(pb->rawbuf==NULL) {
989
                int err;
990
                if((err=grabbuf_alloc(pb)))
991
                        return err;
992
        }
993
 
994
        DBG("PlanB: grab %d: %dx%d fmt %d (%u)\n", pb->grabbing, mp->width,
995
                                                mp->height, fmt, fr);
996
 
997
        if(pb->grabbing >= MAX_GBUFFERS) {
998
                DBG("       no buffer\n");
999
                return -ENOBUFS;
1000
        }
1001
        if(fr > (MAX_GBUFFERS - 1) || fr < 0) {
1002
                DBG("       invalid buffer\n");
1003
                return -EINVAL;
1004
        }
1005
        if(mp->height <= 0 || mp->width <= 0) {
1006
                DBG("       negative height or width\n");
1007
                return -EINVAL;
1008
        }
1009
        if(mp->format < 0 || mp->format >= PLANB_PALETTE_MAX) {
1010
                DBG("       format out of range\n");
1011
                return -EINVAL;
1012
        }
1013
        if(bpp == 0) {
1014
                DBG("       unsupported format %d\n", mp->format);
1015
                return -EINVAL;
1016
        }
1017
        if (mp->height * mp->width * bpp > PLANB_MAX_FBUF) {
1018
                DBG("       grab bigger than buffer\n");
1019
                return -EINVAL;
1020
        }
1021
 
1022
        planb_lock(pb);
1023
        if(mp->width != gbuf->width || mp->height != gbuf->height ||
1024
                        fmt != gbuf->fmt || (gbuf->norm_switch)) {
1025
                int i;
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;
1030
#endif
1031
 
1032
                DBG("PlanB: changed gwidth = %d, gheight = %d, format = %u, "
1033
                        "osize = %d, nsize = %d\n", mp->width, mp->height, fmt,
1034
                                                                osize, nsize);
1035
 
1036
/* Do we _really_ need to clear the grab buffers?? */
1037
#if 0
1038
#ifndef PLANB_GSCANLINE
1039
                if(gbuf->norm_switch)
1040
                        nsize = 0;
1041
                if (nsize < osize) {
1042
                        for(i = gbuf->idx; osize > 0; i++) {
1043
                                memset((void *)pb->rawbuf[i], 0, PAGE_SIZE);
1044
                                osize -= PAGE_SIZE;
1045
                        }
1046
                }
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);
1050
#else
1051
/* XXX TODO */
1052
/*
1053
                if(gbuf->norm_switch)
1054
                        memset((void *)pb->gbuffer[fr], 0,
1055
                                        pb->gbytes_per_line * gbuf->height);
1056
                else {
1057
                        if(mp->
1058
                        for(i = 0; i < gbuf->height; i++) {
1059
                                memset((void *)(pb->gbuffer[fr]
1060
                                        + pb->gbytes_per_line * i
1061
                        }
1062
                }
1063
*/
1064
#endif
1065
#endif /* if 0 */
1066
                gbuf->width = mp->width;
1067
                gbuf->height = mp->height;
1068
                gbuf->fmt = fmt;
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;
1073
        } else
1074
                gbuf->need_pre_capture = 0;
1075
 
1076
        *gbuf->status = GBUFFER_GRABBING;
1077
        if(!(ACTIVE & readl(&pb->planb_base->ch1.status))) {
1078
 
1079
                IDBG("PlanB: ch1 inactive, initiating grabbing\n");
1080
 
1081
                planb_dbdma_stop(&pb->planb_base->ch1);
1082
                if(gbuf->need_pre_capture) {
1083
 
1084
                        DBG("PlanB: padding pre-capture sequence\n");
1085
 
1086
                        writel(virt_to_bus(gbuf->pre_cmd),
1087
                                &pb->planb_base->ch1.cmdptr);
1088
                } else {
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);
1095
                }
1096
                planb_dbdma_restart(&pb->planb_base->ch1);
1097
                pb->last_fr = fr;
1098
        } else {
1099
                int i;
1100
 
1101
                DBG("PlanB: ch1 active, grabbing being queued\n");
1102
 
1103
                if((pb->last_fr == -1) || ((pb->last_fr == -2) &&
1104
                                                overlay_is_active(pb))) {
1105
 
1106
                        DBG("PlanB: overlay is active, grabbing defered\n");
1107
 
1108
                        tab_cmd_dbdma(gbuf->last_cmd, DBDMA_NOP | BR_ALWAYS,
1109
                                        pb->vid_cbo.bus);
1110
                        if(gbuf->need_pre_capture) {
1111
 
1112
                                DBG("PlanB: padding pre-capture sequence\n");
1113
 
1114
                                tab_cmd_store(gbuf->pre_cmd,
1115
                                    virt_to_bus(&pb->overlay_last1->cmd_dep),
1116
                                    pb->vid_cbo.bus);
1117
                                eieio();
1118
                                writel(virt_to_bus(gbuf->pre_cmd),
1119
                                        &pb->overlay_last1->cmd_dep);
1120
                        } else {
1121
                                tab_cmd_store(gbuf->cap_cmd,
1122
                                    virt_to_bus(&pb->overlay_last1->cmd_dep),
1123
                                    pb->vid_cbo.bus);
1124
                                tab_cmd_dbdma((gbuf->cap_cmd + 1),
1125
                                                                DBDMA_NOP, 0);
1126
                                eieio();
1127
                                writel(virt_to_bus(gbuf->cap_cmd),
1128
                                        &pb->overlay_last1->cmd_dep);
1129
                        }
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;
1134
                        pb->last_fr = -2;
1135
                } else if(pb->last_fr == -2) {
1136
 
1137
                        DBG("PlanB: mixed mode detected, grabbing"
1138
                                " will be done before activating overlay\n");
1139
 
1140
                        tab_cmd_dbdma(pb->vid_cbo.start, DBDMA_NOP, 0);
1141
                        if(gbuf->need_pre_capture) {
1142
 
1143
                                DBG("PlanB: padding pre-capture sequence\n");
1144
 
1145
                                tab_cmd_dbdma(pb->gbuf[pb->prev_last_fr].last_cmd,
1146
                                                DBDMA_NOP | BR_ALWAYS,
1147
                                                virt_to_bus(gbuf->pre_cmd));
1148
                                eieio();
1149
                        } else {
1150
                                tab_cmd_dbdma(gbuf->cap_cmd, DBDMA_NOP, 0);
1151
                                if(pb->gbuf[pb->prev_last_fr].width !=
1152
                                                                gbuf->width
1153
                                        || pb->gbuf[pb->prev_last_fr].height !=
1154
                                                                gbuf->height
1155
                                        || pb->gbuf[pb->prev_last_fr].fmt !=
1156
                                                                gbuf->fmt)
1157
                                        tab_cmd_dbdma((gbuf->cap_cmd + 1),
1158
                                                                DBDMA_NOP, 0);
1159
                                else
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));
1166
                                eieio();
1167
                        }
1168
                        tab_cmd_dbdma(gbuf->last_cmd, DBDMA_NOP | BR_ALWAYS,
1169
                                pb->vid_cbo.bus);
1170
                        eieio();
1171
                        pb->prev_last_fr = fr;
1172
                        pb->last_fr = -2;
1173
                } else {
1174
                        gbuf_ptr        lastgbuf = &pb->gbuf[pb->last_fr];
1175
 
1176
                        DBG("PlanB: active grabbing session detected\n");
1177
 
1178
                        if(gbuf->need_pre_capture) {
1179
 
1180
                                DBG("PlanB: padding pre-capture sequence\n");
1181
 
1182
                                tab_cmd_dbdma(lastgbuf->last_cmd,
1183
                                                DBDMA_NOP | BR_ALWAYS,
1184
                                                virt_to_bus(gbuf->pre_cmd));
1185
                                eieio();
1186
                        } else {
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),
1193
                                                                DBDMA_NOP, 0);
1194
                                else
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));
1201
                                eieio();
1202
                        }
1203
                        pb->last_fr = fr;
1204
                }
1205
                if(!(ACTIVE & readl(&pb->planb_base->ch1.status))) {
1206
 
1207
                        DBG("PlanB: became inactive in the mean time... "
1208
                                "reactivating\n");
1209
 
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);
1214
                }
1215
        }
1216
        pb->grabbing++;
1217
        planb_unlock(pb);
1218
 
1219
        return 0;
1220
}
1221
 
1222
static void planb_pre_capture(int fr, struct planb *pb)
1223
{
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;
1228
 
1229
        tab_cmd_dbdma(c1++, DBDMA_NOP, 0);
1230
        c1 = cmd_geo_setup(c1, gbuf->width, height, interlace, gbuf->fmt,
1231
                                                                        0, pb);
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 */
1244
        if (interlace == 0)
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));
1254
cmd_tab_data_end:
1255
        tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(gbuf->cap_cmd));
1256
 
1257
        eieio();
1258
}
1259
 
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.
1270
 */
1271
static dbdma_cmd_ptr setup_grab_cmd(int fr, struct planb *pb)
1272
{
1273
        int             i, count, nlines, stepsize, interlace;
1274
#ifdef PLANB_GSCANLINE
1275
        int             scanline;
1276
#else
1277
        int             nlpp, leftover1;
1278
        unsigned long   base;
1279
#endif
1280
        unsigned long   jump;
1281
        int             pagei;
1282
        dbdma_cmd_ptr   c1;
1283
        dbdma_cmd_ptr   jump_addr;
1284
        gbuf_ptr        gbuf = &pb->gbuf[fr];
1285
        int             fmt = gbuf->fmt;
1286
 
1287
        c1 = gbuf->cap_cmd;
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;
1293
#else
1294
        gbuf->lsize = count;
1295
        gbuf->lnum = 0;
1296
#endif
1297
 
1298
        /* Do video in: */
1299
 
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));
1314
 
1315
        if (interlace) {
1316
                stepsize = 2;
1317
                jump_addr = c1 + TAB_FACTOR * (nlines + 1) / 2;
1318
        } else {
1319
                stepsize = 1;
1320
                jump_addr = c1 + TAB_FACTOR * nlines;
1321
        }
1322
        jump = virt_to_bus(jump_addr);
1323
 
1324
        /* even field data: */
1325
 
1326
        pagei = gbuf->idx;
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]),
1331
                                                                        jump);
1332
        }
1333
#else
1334
        i = 0;
1335
        leftover1 = 0;
1336
        do {
1337
            int j;
1338
 
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);
1344
            if(i < nlines) {
1345
                int lov0 = PAGE_SIZE - count * nlpp * stepsize - leftover1;
1346
 
1347
                if(lov0 == 0)
1348
                    leftover1 = 0;
1349
                else {
1350
                    if(lov0 >= count) {
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);
1355
                    } else {
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! */
1368
                                gbuf->lnum--;
1369
                        }
1370
                    }
1371
                    leftover1 = count * stepsize - lov0;
1372
                    i += stepsize;
1373
                }
1374
            }
1375
            pagei++;
1376
        } while(i < nlines);
1377
        tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, jump);
1378
        c1 = jump_addr;
1379
#endif /* PLANB_GSCANLINE */
1380
 
1381
        /* For non-interlaced, we use even fields only */
1382
        if (!interlace)
1383
                goto cmd_tab_data_end;
1384
 
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));
1393
 
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);
1402
        }
1403
#else
1404
        i = 1;
1405
        leftover1 = 0;
1406
        pagei = gbuf->idx;
1407
        if(nlines <= 1)
1408
            goto skip;
1409
        do {
1410
            int j;
1411
 
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);
1417
                i += stepsize;
1418
            }
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);
1422
            if(i < nlines) {
1423
                int lov0 = PAGE_SIZE - count * nlpp * stepsize - leftover1;
1424
 
1425
                if(lov0 == 0)
1426
                    leftover1 = 0;
1427
                else {
1428
                    if(lov0 > count) {
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
1433
                                                                        - lov0;
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! */
1439
                                gbuf->lnum--;
1440
                        }
1441
                        i += stepsize;
1442
                    }
1443
                    leftover1 = count * stepsize - lov0;
1444
                }
1445
            }
1446
            pagei++;
1447
        } while(i < nlines);
1448
skip:
1449
        tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, jump);
1450
        c1 = jump_addr;
1451
#endif /* PLANB_GSCANLINE */
1452
 
1453
cmd_tab_data_end:
1454
        tab_cmd_store(c1++, (unsigned)(&pb->planb_base_bus->intr_stat),
1455
                        (fr << 9) | PLANB_FRM_IRQ | PLANB_GEN_IRQ);
1456
        /* stop it */
1457
        tab_cmd_dbdma(c1, DBDMA_STOP, 0);
1458
 
1459
        eieio();
1460
        return c1;
1461
}
1462
 
1463
static void planb_irq(int irq, void *dev_id, struct pt_regs * regs)
1464
{
1465
        unsigned int stat, astat;
1466
        struct planb *pb = (struct planb *)dev_id;
1467
 
1468
        IDBG("PlanB: planb_irq()\n");
1469
 
1470
        /* get/clear interrupt status bits */
1471
        eieio();
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);
1477
 
1478
        if(astat & PLANB_FRM_IRQ) {
1479
                unsigned int    fr = stat >> 9;
1480
                gbuf_ptr        gbuf = &pb->gbuf[fr];
1481
#ifndef PLANB_GSCANLINE
1482
                int             i;
1483
#endif
1484
                IDBG("PlanB: PLANB_FRM_IRQ\n");
1485
 
1486
                pb->gcount++;
1487
 
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
1493
                 * they belong. */
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];
1498
 
1499
                        memcpy(pb->l_to_addr[fr][i],
1500
                                pb->rawbuf[gbuf->l_fr_addr_idx + i],
1501
                                first);
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]);
1505
                }
1506
#endif
1507
                *gbuf->status = GBUFFER_DONE;
1508
                pb->grabbing--;
1509
                wake_up_interruptible(&pb->capq);
1510
                return;
1511
        }
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");
1517
}
1518
 
1519
/*******************************
1520
 * Device Operations functions *
1521
 *******************************/
1522
 
1523
static int planb_open(struct video_device *dev, int mode)
1524
{
1525
        struct planb    *pb = (struct planb *)dev->priv;
1526
        int             err;
1527
 
1528
        /* first open on driver? */
1529
        if(pb->vid_user + pb->vbi_user == 0) {
1530
                if((err = planb_prepare_open(pb)) != 0)
1531
                        return err;
1532
        }
1533
        /* first open on video dev? */
1534
        if(pb->vid_user == 0) {
1535
                if((err = planb_prepare_video(pb)) != 0)
1536
                        return err;
1537
        }
1538
        pb->vid_user++;
1539
 
1540
        DBG("PlanB: device opened\n");
1541
 
1542
        MOD_INC_USE_COUNT;
1543
        return 0;
1544
}
1545
 
1546
static void planb_close(struct video_device *dev)
1547
{
1548
        struct planb *pb = (struct planb *)dev->priv;
1549
 
1550
        planb_lock(pb);
1551
        /* last close? then stop everything... */
1552
        if(--pb->vid_user == 0) {
1553
                if(pb->overlay) {
1554
                        planb_dbdma_stop(&pb->planb_base->ch2);
1555
                        planb_dbdma_stop(&pb->planb_base->ch1);
1556
                        pb->overlay = 0;
1557
                }
1558
                planb_close_video(pb);
1559
        }
1560
        /* last open on PlanB hardware? */
1561
        if(pb->vid_user + pb->vbi_user == 0)
1562
                planb_prepare_close(pb);
1563
        planb_unlock(pb);
1564
 
1565
        DBG("PlanB: device closed\n");
1566
 
1567
        MOD_DEC_USE_COUNT;
1568
        return;
1569
}
1570
 
1571
static long planb_read(struct video_device *v, char *buf, unsigned long count,
1572
                                int nonblock)
1573
{
1574
        DBG("planb: read request\n");
1575
        return -EINVAL;
1576
}
1577
 
1578
static long planb_write(struct video_device *v, const char *buf,
1579
                                unsigned long count, int nonblock)
1580
{
1581
        DBG("planb: write request\n");
1582
        return -EINVAL;
1583
}
1584
 
1585
static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
1586
{
1587
        struct planb *pb=(struct planb *)dev->priv;
1588
 
1589
        switch (cmd)
1590
        {
1591
                case VIDIOCGCAP:
1592
                {
1593
                        struct video_capability b;
1594
 
1595
                        DBG("PlanB: IOCTL VIDIOCGCAP\n");
1596
 
1597
                        strcpy (b.name, pb->video_dev.name);
1598
                        b.type = VID_TYPE_OVERLAY | VID_TYPE_CLIPPING |
1599
                                 VID_TYPE_FRAMERAM | VID_TYPE_SCALES |
1600
                                 VID_TYPE_CAPTURE;
1601
                        b.channels = 2; /* composite & svhs */
1602
                        b.audios = 0;
1603
                        b.maxwidth = PLANB_MAXPIXELS;
1604
                        b.maxheight = PLANB_MAXLINES;
1605
                        b.minwidth = 32; /* wild guess */
1606
                        b.minheight = 32;
1607
                        if (copy_to_user(arg,&b,sizeof(b)))
1608
                                return -EFAULT;
1609
                        return 0;
1610
                }
1611
                case VIDIOCSFBUF:
1612
                {
1613
                        struct video_buffer v;
1614
                        unsigned int fmt;
1615
 
1616
                        DBG("PlanB: IOCTL VIDIOCSFBUF\n");
1617
 
1618
                        if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
1619
                                return -EPERM;
1620
                        if (copy_from_user(&v, arg, sizeof(v)))
1621
                                return -EFAULT;
1622
                        planb_lock(pb);
1623
                        switch(v.depth) {
1624
                            /* xawtv only asks for 8 bit in static grey, but
1625
                             * there is no way to know what it really means.. */
1626
                            case 8:
1627
                                fmt = VIDEO_PALETTE_GREY;
1628
                                break;
1629
                            case 15:
1630
                                fmt = VIDEO_PALETTE_RGB555;
1631
                                break;
1632
                            case 32:
1633
                                fmt = VIDEO_PALETTE_RGB32;
1634
                                break;
1635
                            /* We don't deliver these two... */
1636
                            case 16:
1637
                            case 24:
1638
                            default:
1639
                                planb_unlock(pb);
1640
                                return -EINVAL;
1641
                        }
1642
                        if (palette2fmt[fmt].bpp * v.width > v.bytesperline) {
1643
                                planb_unlock(pb);
1644
                                return -EINVAL;
1645
                        }
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;
1654
 
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);
1658
 
1659
                        pb->cmd_buff_inited = 0;
1660
                        if(pb->overlay) {
1661
                                suspend_overlay(pb);
1662
                                fill_cmd_buff(pb);
1663
                                resume_overlay(pb);
1664
                        }
1665
                        planb_unlock(pb);
1666
                        return 0;
1667
                }
1668
                case VIDIOCGFBUF:
1669
                {
1670
                        struct video_buffer v;
1671
 
1672
                        DBG("PlanB: IOCTL VIDIOCGFBUF\n");
1673
 
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)))
1680
                                return -EFAULT;
1681
                        return 0;
1682
                }
1683
                case VIDIOCCAPTURE:
1684
                {
1685
                        int i;
1686
 
1687
                        if(copy_from_user(&i, arg, sizeof(i)))
1688
                                return -EFAULT;
1689
                        if(i==0) {
1690
                                DBG("PlanB: IOCTL VIDIOCCAPTURE Stop\n");
1691
 
1692
                                if (!(pb->overlay))
1693
                                        return 0;
1694
                                planb_lock(pb);
1695
                                pb->overlay = 0;
1696
                                overlay_stop(pb);
1697
                                planb_unlock(pb);
1698
                        } else {
1699
                                DBG("PlanB: IOCTL VIDIOCCAPTURE Start\n");
1700
 
1701
                                if (pb->fb.phys == 0 ||
1702
                                          pb->win.width == 0 ||
1703
                                          pb->win.height == 0)
1704
                                        return -EINVAL;
1705
                                if (pb->overlay)
1706
                                        return 0;
1707
                                planb_lock(pb);
1708
                                pb->overlay = 1;
1709
                                if(!(pb->cmd_buff_inited))
1710
                                        fill_cmd_buff(pb);
1711
                                overlay_start(pb);
1712
                                planb_unlock(pb);
1713
                        }
1714
                        return 0;
1715
                }
1716
                case VIDIOCGCHAN:
1717
                {
1718
                        struct video_channel v;
1719
 
1720
                        DBG("PlanB: IOCTL VIDIOCGCHAN\n");
1721
 
1722
                        if(copy_from_user(&v, arg,sizeof(v)))
1723
                                return -EFAULT;
1724
                        v.flags = 0;
1725
                        v.tuners = 0;
1726
                        v.type = VIDEO_TYPE_CAMERA;
1727
                        v.norm = pb->win.norm;
1728
                        switch(v.channel)
1729
                        {
1730
                        case 0:
1731
                                strcpy(v.name,"Composite");
1732
                                break;
1733
                        case 1:
1734
                                strcpy(v.name,"SVHS");
1735
                                break;
1736
                        default:
1737
                                return -EINVAL;
1738
                                break;
1739
                        }
1740
                        if(copy_to_user(arg,&v,sizeof(v)))
1741
                                return -EFAULT;
1742
 
1743
                        return 0;
1744
                }
1745
                case VIDIOCSCHAN:
1746
                {
1747
                        struct video_channel v;
1748
 
1749
                        DBG("PlanB: IOCTL VIDIOCSCHAN\n");
1750
 
1751
                        if(copy_from_user(&v, arg, sizeof(v)))
1752
                                return -EFAULT;
1753
 
1754
                        if (v.norm != pb->win.norm) {
1755
                                int i, maxlines;
1756
 
1757
                                switch (v.norm)
1758
                                {
1759
                                case VIDEO_MODE_PAL:
1760
                                case VIDEO_MODE_SECAM:
1761
                                        maxlines = PLANB_MAXLINES;
1762
                                        break;
1763
                                case VIDEO_MODE_NTSC:
1764
                                        maxlines = PLANB_NTSC_MAXLINES;
1765
                                        break;
1766
                                default:
1767
                                        DBG("       invalid norm %d.\n", v.norm);
1768
                                        return -EINVAL;
1769
                                        break;
1770
                                }
1771
                                planb_lock(pb);
1772
                                /* empty the grabbing queue */
1773
                                while(pb->grabbing)
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.... */
1782
                                fill_cmd_buff(pb);
1783
                                /* ok, now init it accordingly */
1784
                                saa_init_regs (pb);
1785
                                /* restart overlay if it was running */
1786
                                resume_overlay(pb);
1787
                                planb_unlock(pb);
1788
                        }
1789
 
1790
                        switch(v.channel)
1791
                        {
1792
                        case 0:  /* Composite    */
1793
                                saa_set (SAA7196_IOCC,
1794
                                        ((saa_regs[pb->win.norm][SAA7196_IOCC] &
1795
                                          ~7) | 3), pb);
1796
                                break;
1797
                        case 1: /* SVHS         */
1798
                                saa_set (SAA7196_IOCC,
1799
                                        ((saa_regs[pb->win.norm][SAA7196_IOCC] &
1800
                                          ~7) | 4), pb);
1801
                                break;
1802
                        default:
1803
                                DBG("       invalid channel %d.\n", v.channel);
1804
                                return -EINVAL;
1805
                                break;
1806
                        }
1807
 
1808
                        return 0;
1809
                }
1810
                case VIDIOCGPICT:
1811
                {
1812
                        struct video_picture vp = pb->picture;
1813
 
1814
                        DBG("PlanB: IOCTL VIDIOCGPICT\n");
1815
 
1816
                        vp.palette = pb->win.color_fmt;
1817
                        if(copy_to_user(arg,&vp,sizeof(vp)))
1818
                                return -EFAULT;
1819
                        return 0;
1820
                }
1821
                case VIDIOCSPICT:
1822
                {
1823
                        struct video_picture vp;
1824
 
1825
                        DBG("PlanB: IOCTL VIDIOCSPICT\n");
1826
 
1827
                        if(copy_from_user(&vp,arg,sizeof(vp)))
1828
                                return -EFAULT;
1829
                        pb->picture = vp;
1830
                        /* Should we do sanity checks here? */
1831
                        planb_lock(pb);
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);
1840
                        planb_unlock(pb);
1841
 
1842
                        return 0;
1843
                }
1844
                case VIDIOCSWIN:
1845
                {
1846
                        struct video_window     vw;
1847
                        struct video_clip       clip;
1848
                        int                     i;
1849
 
1850
                        DBG("PlanB: IOCTL VIDIOCSWIN\n");
1851
 
1852
                        if(copy_from_user(&vw,arg,sizeof(vw)))
1853
                                return -EFAULT;
1854
 
1855
                        planb_lock(pb);
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) {
1864
                                pb->win.x = vw.x;
1865
                                pb->win.y = vw.y;
1866
                                pb->win.width = vw.width;
1867
                                pb->win.height = vw.height;
1868
                                fill_cmd_buff(pb);
1869
                        }
1870
                        DBG("PlanB: Window at (%d,%d) size %dx%d\n", vw.x, vw.y, vw.width,
1871
                                vw.height);
1872
 
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)))
1880
                                        return -EFAULT;
1881
                                add_clip(pb, &clip);
1882
                        }
1883
                        /* restart overlay if it was running */
1884
                        resume_overlay(pb);
1885
                        planb_unlock(pb);
1886
                        return 0;
1887
                }
1888
                case VIDIOCGWIN:
1889
                {
1890
                        struct video_window vw;
1891
 
1892
                        DBG("PlanB: IOCTL VIDIOCGWIN\n");
1893
 
1894
                        vw.x=pb->win.x;
1895
                        vw.y=pb->win.y;
1896
                        vw.width=pb->win.width;
1897
                        vw.height=pb->win.height;
1898
                        vw.chromakey=0;
1899
                        vw.flags=0;
1900
                        if(pb->win.interlace)
1901
                                vw.flags|=VIDEO_WINDOW_INTERLACE;
1902
                        if(copy_to_user(arg,&vw,sizeof(vw)))
1903
                                return -EFAULT;
1904
                        return 0;
1905
                }
1906
                case VIDIOCSYNC: {
1907
                        int             i;
1908
                        gbuf_ptr        gbuf;
1909
 
1910
                        DBG("PlanB: IOCTL VIDIOCSYNC\n");
1911
 
1912
                        if(copy_from_user((void *)&i,arg,sizeof(int)))
1913
                                return -EFAULT;
1914
 
1915
                        DBG("PlanB: sync to frame %d\n", i);
1916
 
1917
                        if(i > (MAX_GBUFFERS - 1) || i < 0)
1918
                                return -EINVAL;
1919
                        gbuf = &pb->gbuf[i];
1920
chk_grab:
1921
                        switch (*gbuf->status) {
1922
                        case GBUFFER_UNUSED:
1923
                                return -EINVAL;
1924
                        case GBUFFER_GRABBING:
1925
                                DBG("PlanB: waiting for grab"
1926
                                                        " done (%d)\n", i);
1927
                                interruptible_sleep_on(&pb->capq);
1928
                                if(signal_pending(current))
1929
                                        return -EINTR;
1930
                                goto chk_grab;
1931
                        case GBUFFER_DONE:
1932
                                *gbuf->status = GBUFFER_UNUSED;
1933
                                break;
1934
                        }
1935
                        return 0;
1936
                }
1937
 
1938
                case VIDIOCMCAPTURE:
1939
                {
1940
                        struct video_mmap vm;
1941
                        int               fr;
1942
 
1943
                        DBG("PlanB: IOCTL VIDIOCMCAPTURE\n");
1944
 
1945
                        if(copy_from_user((void *) &vm,(void *)arg,sizeof(vm)))
1946
                                return -EFAULT;
1947
                        fr = vm.frame;
1948
                        if(fr > (MAX_GBUFFERS - 1) || fr < 0)
1949
                                return -EINVAL;
1950
                        if (*pb->gbuf[fr].status != GBUFFER_UNUSED)
1951
                                return -EBUSY;
1952
 
1953
                        return vgrab(pb, &vm);
1954
                }
1955
 
1956
                case VIDIOCGMBUF:
1957
                {
1958
                        int i;
1959
                        struct video_mbuf vm;
1960
 
1961
                        DBG("PlanB: IOCTL VIDIOCGMBUF\n");
1962
 
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)))
1969
                                return -EFAULT;
1970
                        return 0;
1971
                }
1972
 
1973
                case VIDIOCGUNIT:
1974
                {
1975
                        struct video_unit vu;
1976
 
1977
                        DBG("PlanB: IOCTL VIDIOCGUNIT\n");
1978
 
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)))
1985
                                return -EFAULT;
1986
                        return 0;
1987
                }
1988
 
1989
                case PLANBIOCGSAAREGS:
1990
                {
1991
                        struct planb_saa_regs preg;
1992
 
1993
                        DBG("PlanB: IOCTL PLANBIOCGSAAREGS\n");
1994
 
1995
                        if(copy_from_user(&preg, arg, sizeof(preg)))
1996
                                return -EFAULT;
1997
                        if(preg.addr >= SAA7196_NUMREGS)
1998
                                return -EINVAL;
1999
                        preg.val = saa_regs[pb->win.norm][preg.addr];
2000
                        if(copy_to_user((void *)arg, (void *)&preg,
2001
                                                                sizeof(preg)))
2002
                                return -EFAULT;
2003
                        return 0;
2004
                }
2005
 
2006
                case PLANBIOCSSAAREGS:
2007
                {
2008
                        struct planb_saa_regs preg;
2009
 
2010
                        DBG("PlanB: IOCTL PLANBIOCSSAAREGS\n");
2011
 
2012
                        if(copy_from_user(&preg, arg, sizeof(preg)))
2013
                                return -EFAULT;
2014
                        if(preg.addr >= SAA7196_NUMREGS)
2015
                                return -EINVAL;
2016
                        saa_set (preg.addr, preg.val, pb);
2017
                        return 0;
2018
                }
2019
 
2020
                case PLANBIOCGSTAT:
2021
                {
2022
                        struct planb_stat_regs pstat;
2023
 
2024
                        DBG("PlanB: IOCTL PLANBIOCGSTAT\n");
2025
 
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);
2034
 
2035
                        if(copy_to_user((void *)arg, (void *)&pstat,
2036
                                                        sizeof(pstat)))
2037
                                return -EFAULT;
2038
                        return 0;
2039
                }
2040
 
2041
                case PLANBIOCSMODE: {
2042
                        int v;
2043
 
2044
                        DBG("PlanB: IOCTL PLANBIOCSMODE\n");
2045
 
2046
                        if(copy_from_user(&v, arg, sizeof(v)))
2047
                                return -EFAULT;
2048
 
2049
                        switch(v)
2050
                        {
2051
                        case PLANB_TV_MODE:
2052
                                saa_set (SAA7196_STDC,
2053
                                        (saa_regs[pb->win.norm][SAA7196_STDC] &
2054
                                          0x7f), pb);
2055
                                break;
2056
                        case PLANB_VTR_MODE:
2057
                                saa_set (SAA7196_STDC,
2058
                                        (saa_regs[pb->win.norm][SAA7196_STDC] |
2059
                                          0x80), pb);
2060
                                break;
2061
                        default:
2062
                                return -EINVAL;
2063
                                break;
2064
                        }
2065
                        pb->win.mode = v;
2066
                        return 0;
2067
                }
2068
                case PLANBIOCGMODE: {
2069
                        int v=pb->win.mode;
2070
 
2071
                        DBG("PlanB: IOCTL PLANBIOCGMODE\n");
2072
 
2073
                        if(copy_to_user(arg,&v,sizeof(v)))
2074
                                return -EFAULT;
2075
                        return 0;
2076
                }
2077
#ifdef PLANB_GSCANLINE
2078
                case PLANBG_GRAB_BPL: {
2079
                        int v=pb->gbytes_per_line;
2080
 
2081
                        DBG("PlanB: IOCTL PLANBG_GRAB_BPL\n");
2082
 
2083
                        if(copy_to_user(arg,&v,sizeof(v)))
2084
                                return -EFAULT;
2085
                        return 0;
2086
                }
2087
#endif /* PLANB_GSCANLINE */
2088
 
2089
/* These serve only for debugging... */
2090
#ifdef DEBUG
2091
                case PLANB_INTR_DEBUG: {
2092
                        int i;
2093
 
2094
                        DBG("PlanB: IOCTL PLANB_INTR_DEBUG\n");
2095
 
2096
                        if(copy_from_user(&i, arg, sizeof(i)))
2097
                                return -EFAULT;
2098
 
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;
2103
                                }
2104
                        }
2105
                        if(pb->grabbing)
2106
                                pb->grabbing--;
2107
                        wake_up_interruptible(&pb->capq);
2108
                        return 0;
2109
                }
2110
                case PLANB_INV_REGS: {
2111
                        int i;
2112
                        struct planb_any_regs any;
2113
 
2114
                        DBG("PlanB: IOCTL PLANB_INV_REGS\n");
2115
 
2116
                        if(copy_from_user(&any, arg, sizeof(any)))
2117
                                return -EFAULT;
2118
                        if(any.offset < 0 || any.offset + any.bytes > 0x400)
2119
                                return -EINVAL;
2120
                        if(any.bytes > 128)
2121
                                return -EINVAL;
2122
                        for (i = 0; i < any.bytes; i++) {
2123
                                any.data[i] =
2124
                                        readb((unsigned char *)pb->planb_base
2125
                                                        + any.offset + i);
2126
                        }
2127
                        if(copy_to_user(arg,&any,sizeof(any)))
2128
                                return -EFAULT;
2129
                        return 0;
2130
                }
2131
                case PLANBIOCGDBDMABUF:
2132
                {
2133
                        struct planb_buf_regs buf;
2134
                        dbdma_cmd_ptr dc;
2135
                        int i;
2136
 
2137
                        DBG("PlanB: IOCTL PLANBIOCGDBDMABUF\n");
2138
 
2139
                        if(copy_from_user(&buf, arg, sizeof(buf)))
2140
                                return -EFAULT;
2141
                        buf.end &= ~0xf;
2142
                        if( (buf.start < 0) || (buf.end < 0x10) ||
2143
                            (buf.end < buf.start+0x10) ||
2144
                            (buf.end > 2*pb->tab_size) )
2145
                                return -EINVAL;
2146
 
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);
2154
                        }
2155
                        return 0;
2156
                }
2157
#endif /* DEBUG */
2158
 
2159
                default:
2160
                {
2161
                        DBG("PlanB: Unimplemented IOCTL: %d (0x%x)\n", cmd, cmd);
2162
                        return -ENOIOCTLCMD;
2163
                }
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; }
2171
                case VIDIOCSFREQ: {
2172
                DBG("PlanB: IOCTL VIDIOCSFREQ\n");
2173
                        goto unimplemented; }
2174
                case VIDIOCGFREQ: {
2175
                DBG("PlanB: IOCTL VIDIOCGFREQ\n");
2176
                        goto unimplemented; }
2177
                case VIDIOCKEY: {
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; }
2186
unimplemented:
2187
                DBG("       Unimplemented\n");
2188
                        return -ENOIOCTLCMD;
2189
        }
2190
        return 0;
2191
}
2192
 
2193
static int planb_mmap(struct video_device *dev, const char *adr, unsigned long size)
2194
{
2195
        struct planb    *pb = (struct planb *)dev->priv;
2196
        unsigned long   start = (unsigned long)adr;
2197
        int             i;
2198
 
2199
        if (size > MAX_GBUFFERS * PLANB_MAX_FBUF)
2200
                return -EINVAL;
2201
        if (!pb->rawbuf) {
2202
                int err;
2203
                if((err=grabbuf_alloc(pb)))
2204
                        return err;
2205
        }
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))
2209
                        return -EAGAIN;
2210
                start += PAGE_SIZE;
2211
                if (size <= PAGE_SIZE)
2212
                        break;
2213
                size -= PAGE_SIZE;
2214
        }
2215
        return 0;
2216
}
2217
 
2218
/**********************************
2219
 * VBI device operation functions *
2220
 **********************************/
2221
 
2222
static long planb_vbi_read(struct video_device *dev, char *buf,
2223
        unsigned long count, int nonblock)
2224
{
2225
        struct planb    *pb = (struct planb *)dev->priv;
2226
        int             q,todo;
2227
        DECLARE_WAITQUEUE(wait, current);
2228
 
2229
/* Dummy for now */
2230
        printk ("PlanB: VBI read %li bytes.\n", count);
2231
        return (0);
2232
 
2233
        todo=count;
2234
        while (todo && todo>(q=VBIBUF_SIZE-pb->vbip))
2235
        {
2236
                if(copy_to_user((void *) buf, (void *) pb->vbibuf+pb->vbip, q))
2237
                        return -EFAULT;
2238
                todo-=q;
2239
                buf+=q;
2240
 
2241
                add_wait_queue(&pb->vbiq, &wait);
2242
                current->state = TASK_INTERRUPTIBLE;
2243
                if (todo && q==VBIBUF_SIZE-pb->vbip) {
2244
                        if(nonblock) {
2245
                                remove_wait_queue(&pb->vbiq, &wait);
2246
                                current->state = TASK_RUNNING;
2247
                                if(count==todo)
2248
                                        return -EWOULDBLOCK;
2249
                                return count-todo;
2250
                        }
2251
                        schedule();
2252
                        if(signal_pending(current)) {
2253
                                remove_wait_queue(&pb->vbiq, &wait);
2254
                                current->state = TASK_RUNNING;
2255
                                if(todo==count)
2256
                                        return -EINTR;
2257
                                else
2258
                                        return count-todo;
2259
                        }
2260
                }
2261
                remove_wait_queue(&pb->vbiq, &wait);
2262
                current->state = TASK_RUNNING;
2263
        }
2264
        if (todo) {
2265
                if(copy_to_user((void *) buf, (void *) pb->vbibuf+pb->vbip,
2266
                    todo))
2267
                        return -EFAULT;
2268
                pb->vbip+=todo;
2269
        }
2270
        return count;
2271
}
2272
 
2273
static unsigned int planb_vbi_poll(struct video_device *dev,
2274
        struct file *file, poll_table *wait)
2275
{
2276
        struct planb    *pb = (struct planb *)dev->priv;
2277
        unsigned int    mask = 0;
2278
 
2279
        printk ("PlanB: VBI poll.\n");
2280
        poll_wait(file, &pb->vbiq, wait);
2281
 
2282
        if (pb->vbip < VBIBUF_SIZE)
2283
                mask |= (POLLIN | POLLRDNORM);
2284
 
2285
        return mask;
2286
}
2287
 
2288
static int planb_vbi_open(struct video_device *dev, int flags)
2289
{
2290
        struct planb    *pb = (struct planb *)dev->priv;
2291
        int             err;
2292
 
2293
        /* first open on the driver? */
2294
        if(pb->vid_user + pb->vbi_user == 0) {
2295
                if((err = planb_prepare_open(pb)) != 0)
2296
                        return err;
2297
        }
2298
        /* first open on the vbi device? */
2299
        if(pb->vbi_user == 1) {
2300
                if((err = planb_prepare_vbi(pb)) != 0)
2301
                        return err;
2302
        }
2303
        ++pb->vbi_user;
2304
 
2305
        DBG("PlanB: VBI open\n");
2306
 
2307
        MOD_INC_USE_COUNT;
2308
        return 0;
2309
}
2310
 
2311
static void planb_vbi_close(struct video_device *dev)
2312
{
2313
        struct planb    *pb = (struct planb *)dev->priv;
2314
 
2315
        /* last close on vbi device? */
2316
        if(--pb->vbi_user == 0) {
2317
                planb_close_vbi(pb);
2318
        }
2319
        /* last close on any planb device? */
2320
        if(pb->vid_user + pb->vbi_user == 0) {
2321
                planb_prepare_close(pb);
2322
        }
2323
 
2324
        DBG("PlanB: VBI close\n");
2325
 
2326
        MOD_DEC_USE_COUNT;
2327
        return;
2328
}
2329
 
2330
static int planb_vbi_ioctl(struct video_device *dev, unsigned int cmd,
2331
        void *arg)
2332
{
2333
        switch (cmd) {
2334
                /* This is only for alevt */
2335
                case BTTV_VBISIZE:
2336
                        DBG("PlanB: IOCTL BTTV_VBISIZE.\n");
2337
                        return VBIBUF_SIZE;
2338
                default:
2339
                        DBG("PlanB: Unimplemented VBI IOCTL no. %i.\n", cmd);
2340
                        return -EINVAL;
2341
        }
2342
}
2343
 
2344
static struct video_device planb_template=
2345
{
2346
        owner:          THIS_MODULE,
2347
        name:           PLANB_DEVICE_NAME,
2348
        type:           VID_TYPE_CAPTURE|VID_TYPE_OVERLAY,
2349
        hardware:       VID_HARDWARE_PLANB,
2350
        open:           planb_open,
2351
        close:          planb_close,
2352
        read:           planb_read,
2353
        write:          planb_write,    /* not implemented */
2354
        ioctl:          planb_ioctl,
2355
        mmap:           planb_mmap,     /* mmap? */
2356
};
2357
 
2358
static struct video_device planb_vbi_template=
2359
{
2360
        owner:          THIS_MODULE,
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,
2370
};
2371
 
2372
static int __devinit init_planb(struct planb *pb)
2373
{
2374
        unsigned char saa_rev;
2375
        int i, result;
2376
        unsigned long flags;
2377
 
2378
        printk(KERN_INFO "PlanB: PowerMacintosh video input driver rev. %s\n", PLANB_REV);
2379
 
2380
        pb->video_dev.minor = -1;
2381
        pb->vid_user = 0;
2382
 
2383
        /* Simple sanity check */
2384
        if(def_norm >= NUM_SUPPORTED_NORM || def_norm < 0) {
2385
                printk(KERN_ERR "PlanB: Option(s) invalid\n");
2386
                return -2;
2387
        }
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;
2392
        pb->win.x = 0;
2393
        pb->win.y = 0;
2394
        pb->win.width = 768; /* 640 */
2395
        pb->win.height = 576; /* 480 */
2396
        pb->win.pad = 0;
2397
        pb->win.bpp = 4;
2398
        pb->win.depth = 32;
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;
2403
        pb->maxlines = 576;
2404
#ifdef PLANB_GSCANLINE
2405
        if((pb->gbytes_per_line = PLANB_MAXPIXELS * 4) > PAGE_SIZE
2406
                                || (pb->gbytes_per_line <= 0))
2407
                return -3;
2408
        else {
2409
                /* page align pb->gbytes_per_line for DMA purpose */
2410
                for(i = PAGE_SIZE; pb->gbytes_per_line < (i >> 1);)
2411
                        i >>= 1;
2412
                pb->gbytes_per_line = i;
2413
        }
2414
#endif
2415
        pb->tab_size = PLANB_MAXLINES + 40;
2416
        pb->suspend = 0;
2417
        init_MUTEX(&pb->lock);
2418
        pb->vid_cbo.start = 0;
2419
        pb->clip_cbo.start = 0;
2420
        pb->mask = 0;
2421
        pb->vid_raw = 0;
2422
        pb->overlay = 0;
2423
        init_waitqueue_head(&pb->suspendq);
2424
        pb->cmd_buff_inited = 0;
2425
        pb->fb.phys = 0;
2426
        pb->fb.offset = 0;
2427
 
2428
        /* VBI stuff: */
2429
        pb->vbi_dev.minor = -1;
2430
        pb->vbi_user = 0;
2431
        pb->vbirunning = 0;
2432
        pb->vbip = 0;
2433
        pb->vbibuf = 0;
2434
        init_waitqueue_head(&pb->vbiq);
2435
 
2436
        /* Reset DMA controllers */
2437
        planb_dbdma_stop(&pb->planb_base->ch2);
2438
        planb_dbdma_stop(&pb->planb_base->ch1);
2439
 
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 */
2443
        saa_init_regs (pb);
2444
 
2445
        /* clear interrupt mask */
2446
        pb->intr_mask = PLANB_CLR_IRQ;
2447
 
2448
        save_flags(flags); cli();
2449
        result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb);
2450
        if (result < 0) {
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);
2458
                return result;
2459
        }
2460
        disable_irq(pb->irq);
2461
        restore_flags(flags);
2462
 
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;
2469
 
2470
        init_waitqueue_head(&pb->capq);
2471
        for(i=0; i<MAX_GBUFFERS; i++) {
2472
                gbuf_ptr        gbuf = &pb->gbuf[i];
2473
 
2474
                gbuf->idx = PLANB_MAX_FBUF * i / PAGE_SIZE;
2475
                gbuf->width=0;
2476
                gbuf->height=0;
2477
                gbuf->fmt=0;
2478
                gbuf->cap_cmd=NULL;
2479
#ifndef PLANB_GSCANLINE
2480
                gbuf->l_fr_addr_idx = MAX_GBUFFERS * (PLANB_MAX_FBUF
2481
                                                / PAGE_SIZE + 1) + MAX_LNUM * i;
2482
                gbuf->lsize = 0;
2483
                gbuf->lnum = 0;
2484
#endif
2485
        }
2486
        pb->rawbuf=NULL;
2487
        pb->grabbing=0;
2488
 
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);
2493
 
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));
2498
 
2499
        if(video_register_device(&pb->video_dev, VFL_TYPE_GRABBER, video_nr)<0)
2500
                return -1;
2501
        if(video_register_device(&pb->vbi_dev, VFL_TYPE_VBI, vbi_nr)<0) {
2502
                video_unregister_device(&pb->video_dev);
2503
                return -1;
2504
        }
2505
 
2506
        return 0;
2507
}
2508
 
2509
/*
2510
 *      Scan for a PlanB controller and map the io memory
2511
 */
2512
static int find_planb(void)
2513
{
2514
        struct planb            *pb;
2515
        struct pci_dev          *pdev = NULL;
2516
        unsigned long           base;
2517
        int                     planb_num = 0;
2518
 
2519
        if (_machine != _MACH_Pmac)
2520
                return 0;
2521
 
2522
        pdev = pci_find_device(APPLE_VENDOR_ID, PLANB_DEV_ID, pdev);
2523
        if (pdev == NULL) {
2524
                printk(KERN_WARNING "PlanB: no device found!\n");
2525
                return planb_num;
2526
        }
2527
 
2528
        pb = &planbs;
2529
        planb_num = 1;
2530
        base = pdev->resource[0].start;
2531
 
2532
        DBG("PlanB: Found device %s, membase 0x%lx, irq %d\n",
2533
                pdev->slot_name, base, pdev->irq);
2534
 
2535
        /* Enable response in memory space, bus mastering,
2536
           use memory write and invalidate */
2537
        pci_enable_device (pdev);
2538
        pci_set_master (pdev);
2539
        pci_set_mwi(pdev);
2540
        /* value copied from MacOS... */
2541
        pci_write_config_byte (pdev, PCI_LATENCY_TIMER, 0x40);
2542
 
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;
2548
 
2549
        return planb_num;
2550
}
2551
 
2552
static void release_planb(void)
2553
{
2554
        struct planb *pb;
2555
 
2556
        pb=&planbs;
2557
 
2558
        /* stop and flush DMAs unconditionally */
2559
        planb_dbdma_stop(&pb->planb_base->ch2);
2560
        planb_dbdma_stop(&pb->planb_base->ch1);
2561
 
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);
2566
 
2567
        /* make sure all allocated memory are freed */
2568
        planb_prepare_close(pb);
2569
 
2570
        printk(KERN_INFO "PlanB: unregistering with v4l\n");
2571
        video_unregister_device(&pb->video_dev);
2572
        video_unregister_device(&pb->vbi_dev);
2573
 
2574
        /* note that iounmap() does nothing on the PPC right now */
2575
        iounmap ((void *)pb->planb_base);
2576
}
2577
 
2578
static int __init init_planbs(void)
2579
{
2580
        int planb_num;
2581
 
2582
        planb_num=find_planb();
2583
 
2584
        if (planb_num < 0)
2585
                return -EIO;
2586
        if (planb_num == 0)
2587
                return -ENXIO;
2588
 
2589
        if (init_planb(&planbs) < 0) {
2590
                printk(KERN_ERR "PlanB: error registering planb device"
2591
                                                " with v4l\n");
2592
                release_planb();
2593
                return -EIO;
2594
        }
2595
        return 0;
2596
}
2597
 
2598
static void __exit exit_planbs(void)
2599
{
2600
        release_planb();
2601
}
2602
 
2603
module_init(init_planbs);
2604
module_exit(exit_planbs);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.