Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/video/bt8xx/bttv-risc.c
10785 views
1
/*
2
3
bttv-risc.c -- interfaces to other kernel modules
4
5
bttv risc code handling
6
- memory management
7
- generation
8
9
(c) 2000-2003 Gerd Knorr <[email protected]>
10
11
This program is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation; either version 2 of the License, or
14
(at your option) any later version.
15
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
GNU General Public License for more details.
20
21
You should have received a copy of the GNU General Public License
22
along with this program; if not, write to the Free Software
23
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
25
*/
26
27
#include <linux/module.h>
28
#include <linux/init.h>
29
#include <linux/slab.h>
30
#include <linux/pci.h>
31
#include <linux/vmalloc.h>
32
#include <linux/interrupt.h>
33
#include <asm/page.h>
34
#include <asm/pgtable.h>
35
#include <media/v4l2-ioctl.h>
36
37
#include "bttvp.h"
38
39
#define VCR_HACK_LINES 4
40
41
/* ---------------------------------------------------------- */
42
/* risc code generators */
43
44
int
45
bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
46
struct scatterlist *sglist,
47
unsigned int offset, unsigned int bpl,
48
unsigned int padding, unsigned int skip_lines,
49
unsigned int store_lines)
50
{
51
u32 instructions,line,todo;
52
struct scatterlist *sg;
53
__le32 *rp;
54
int rc;
55
56
/* estimate risc mem: worst case is one write per page border +
57
one write per scan line + sync + jump (all 2 dwords). padding
58
can cause next bpl to start close to a page border. First DMA
59
region may be smaller than PAGE_SIZE */
60
instructions = skip_lines * 4;
61
instructions += (1 + ((bpl + padding) * store_lines)
62
/ PAGE_SIZE + store_lines) * 8;
63
instructions += 2 * 8;
64
if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0)
65
return rc;
66
67
/* sync instruction */
68
rp = risc->cpu;
69
*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
70
*(rp++) = cpu_to_le32(0);
71
72
while (skip_lines-- > 0) {
73
*(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
74
BT848_RISC_EOL | bpl);
75
}
76
77
/* scan lines */
78
sg = sglist;
79
for (line = 0; line < store_lines; line++) {
80
if ((btv->opt_vcr_hack) &&
81
(line >= (store_lines - VCR_HACK_LINES)))
82
continue;
83
while (offset && offset >= sg_dma_len(sg)) {
84
offset -= sg_dma_len(sg);
85
sg++;
86
}
87
if (bpl <= sg_dma_len(sg)-offset) {
88
/* fits into current chunk */
89
*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
90
BT848_RISC_EOL|bpl);
91
*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
92
offset+=bpl;
93
} else {
94
/* scanline needs to be splitted */
95
todo = bpl;
96
*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
97
(sg_dma_len(sg)-offset));
98
*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
99
todo -= (sg_dma_len(sg)-offset);
100
offset = 0;
101
sg++;
102
while (todo > sg_dma_len(sg)) {
103
*(rp++)=cpu_to_le32(BT848_RISC_WRITE|
104
sg_dma_len(sg));
105
*(rp++)=cpu_to_le32(sg_dma_address(sg));
106
todo -= sg_dma_len(sg);
107
sg++;
108
}
109
*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
110
todo);
111
*(rp++)=cpu_to_le32(sg_dma_address(sg));
112
offset += todo;
113
}
114
offset += padding;
115
}
116
117
/* save pointer to jmp instruction address */
118
risc->jmp = rp;
119
BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
120
return 0;
121
}
122
123
static int
124
bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
125
struct scatterlist *sglist,
126
unsigned int yoffset, unsigned int ybpl,
127
unsigned int ypadding, unsigned int ylines,
128
unsigned int uoffset, unsigned int voffset,
129
unsigned int hshift, unsigned int vshift,
130
unsigned int cpadding)
131
{
132
unsigned int instructions,line,todo,ylen,chroma;
133
__le32 *rp;
134
u32 ri;
135
struct scatterlist *ysg;
136
struct scatterlist *usg;
137
struct scatterlist *vsg;
138
int topfield = (0 == yoffset);
139
int rc;
140
141
/* estimate risc mem: worst case is one write per page border +
142
one write per scan line (5 dwords)
143
plus sync + jump (2 dwords) */
144
instructions = ((3 + (ybpl + ypadding) * ylines * 2)
145
/ PAGE_SIZE) + ylines;
146
instructions += 2;
147
if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
148
return rc;
149
150
/* sync instruction */
151
rp = risc->cpu;
152
*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
153
*(rp++) = cpu_to_le32(0);
154
155
/* scan lines */
156
ysg = sglist;
157
usg = sglist;
158
vsg = sglist;
159
for (line = 0; line < ylines; line++) {
160
if ((btv->opt_vcr_hack) &&
161
(line >= (ylines - VCR_HACK_LINES)))
162
continue;
163
switch (vshift) {
164
case 0:
165
chroma = 1;
166
break;
167
case 1:
168
if (topfield)
169
chroma = ((line & 1) == 0);
170
else
171
chroma = ((line & 1) == 1);
172
break;
173
case 2:
174
if (topfield)
175
chroma = ((line & 3) == 0);
176
else
177
chroma = ((line & 3) == 2);
178
break;
179
default:
180
chroma = 0;
181
break;
182
}
183
184
for (todo = ybpl; todo > 0; todo -= ylen) {
185
/* go to next sg entry if needed */
186
while (yoffset && yoffset >= sg_dma_len(ysg)) {
187
yoffset -= sg_dma_len(ysg);
188
ysg++;
189
}
190
while (uoffset && uoffset >= sg_dma_len(usg)) {
191
uoffset -= sg_dma_len(usg);
192
usg++;
193
}
194
while (voffset && voffset >= sg_dma_len(vsg)) {
195
voffset -= sg_dma_len(vsg);
196
vsg++;
197
}
198
199
/* calculate max number of bytes we can write */
200
ylen = todo;
201
if (yoffset + ylen > sg_dma_len(ysg))
202
ylen = sg_dma_len(ysg) - yoffset;
203
if (chroma) {
204
if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
205
ylen = (sg_dma_len(usg) - uoffset) << hshift;
206
if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
207
ylen = (sg_dma_len(vsg) - voffset) << hshift;
208
ri = BT848_RISC_WRITE123;
209
} else {
210
ri = BT848_RISC_WRITE1S23;
211
}
212
if (ybpl == todo)
213
ri |= BT848_RISC_SOL;
214
if (ylen == todo)
215
ri |= BT848_RISC_EOL;
216
217
/* write risc instruction */
218
*(rp++)=cpu_to_le32(ri | ylen);
219
*(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
220
(ylen >> hshift));
221
*(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
222
yoffset += ylen;
223
if (chroma) {
224
*(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
225
uoffset += ylen >> hshift;
226
*(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
227
voffset += ylen >> hshift;
228
}
229
}
230
yoffset += ypadding;
231
if (chroma) {
232
uoffset += cpadding;
233
voffset += cpadding;
234
}
235
}
236
237
/* save pointer to jmp instruction address */
238
risc->jmp = rp;
239
BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
240
return 0;
241
}
242
243
static int
244
bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
245
const struct bttv_format *fmt, struct bttv_overlay *ov,
246
int skip_even, int skip_odd)
247
{
248
int dwords, rc, line, maxy, start, end;
249
unsigned skip, nskips;
250
struct btcx_skiplist *skips;
251
__le32 *rp;
252
u32 ri,ra;
253
u32 addr;
254
255
/* skip list for window clipping */
256
if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
257
return -ENOMEM;
258
259
/* estimate risc mem: worst case is (1.5*clip+1) * lines instructions
260
+ sync + jump (all 2 dwords) */
261
dwords = (3 * ov->nclips + 2) *
262
((skip_even || skip_odd) ? (ov->w.height+1)>>1 : ov->w.height);
263
dwords += 4;
264
if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) {
265
kfree(skips);
266
return rc;
267
}
268
269
/* sync instruction */
270
rp = risc->cpu;
271
*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
272
*(rp++) = cpu_to_le32(0);
273
274
addr = (unsigned long)btv->fbuf.base;
275
addr += btv->fbuf.fmt.bytesperline * ov->w.top;
276
addr += (fmt->depth >> 3) * ov->w.left;
277
278
/* scan lines */
279
for (maxy = -1, line = 0; line < ov->w.height;
280
line++, addr += btv->fbuf.fmt.bytesperline) {
281
if ((btv->opt_vcr_hack) &&
282
(line >= (ov->w.height - VCR_HACK_LINES)))
283
continue;
284
if ((line%2) == 0 && skip_even)
285
continue;
286
if ((line%2) == 1 && skip_odd)
287
continue;
288
289
/* calculate clipping */
290
if (line > maxy)
291
btcx_calc_skips(line, ov->w.width, &maxy,
292
skips, &nskips, ov->clips, ov->nclips);
293
294
/* write out risc code */
295
for (start = 0, skip = 0; start < ov->w.width; start = end) {
296
if (skip >= nskips) {
297
ri = BT848_RISC_WRITE;
298
end = ov->w.width;
299
} else if (start < skips[skip].start) {
300
ri = BT848_RISC_WRITE;
301
end = skips[skip].start;
302
} else {
303
ri = BT848_RISC_SKIP;
304
end = skips[skip].end;
305
skip++;
306
}
307
if (BT848_RISC_WRITE == ri)
308
ra = addr + (fmt->depth>>3)*start;
309
else
310
ra = 0;
311
312
if (0 == start)
313
ri |= BT848_RISC_SOL;
314
if (ov->w.width == end)
315
ri |= BT848_RISC_EOL;
316
ri |= (fmt->depth>>3) * (end-start);
317
318
*(rp++)=cpu_to_le32(ri);
319
if (0 != ra)
320
*(rp++)=cpu_to_le32(ra);
321
}
322
}
323
324
/* save pointer to jmp instruction address */
325
risc->jmp = rp;
326
BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
327
kfree(skips);
328
return 0;
329
}
330
331
/* ---------------------------------------------------------- */
332
333
static void
334
bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
335
int width, int height, int interleaved,
336
const struct bttv_tvnorm *tvnorm)
337
{
338
u32 xsf, sr;
339
int vdelay;
340
341
int swidth = tvnorm->swidth;
342
int totalwidth = tvnorm->totalwidth;
343
int scaledtwidth = tvnorm->scaledtwidth;
344
345
if (btv->input == btv->dig) {
346
swidth = 720;
347
totalwidth = 858;
348
scaledtwidth = 858;
349
}
350
351
vdelay = tvnorm->vdelay;
352
353
xsf = (width*scaledtwidth)/swidth;
354
geo->hscale = ((totalwidth*4096UL)/xsf-4096);
355
geo->hdelay = tvnorm->hdelayx1;
356
geo->hdelay = (geo->hdelay*width)/swidth;
357
geo->hdelay &= 0x3fe;
358
sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
359
geo->vscale = (0x10000UL-sr) & 0x1fff;
360
geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
361
((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
362
geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
363
geo->vdelay = vdelay;
364
geo->width = width;
365
geo->sheight = tvnorm->sheight;
366
geo->vtotal = tvnorm->vtotal;
367
368
if (btv->opt_combfilter) {
369
geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
370
geo->comb = (width < 769) ? 1 : 0;
371
} else {
372
geo->vtc = 0;
373
geo->comb = 0;
374
}
375
}
376
377
static void
378
bttv_calc_geo (struct bttv * btv,
379
struct bttv_geometry * geo,
380
unsigned int width,
381
unsigned int height,
382
int both_fields,
383
const struct bttv_tvnorm * tvnorm,
384
const struct v4l2_rect * crop)
385
{
386
unsigned int c_width;
387
unsigned int c_height;
388
u32 sr;
389
390
if ((crop->left == tvnorm->cropcap.defrect.left
391
&& crop->top == tvnorm->cropcap.defrect.top
392
&& crop->width == tvnorm->cropcap.defrect.width
393
&& crop->height == tvnorm->cropcap.defrect.height
394
&& width <= tvnorm->swidth /* see PAL-Nc et al */)
395
|| btv->input == btv->dig) {
396
bttv_calc_geo_old(btv, geo, width, height,
397
both_fields, tvnorm);
398
return;
399
}
400
401
/* For bug compatibility the image size checks permit scale
402
factors > 16. See bttv_crop_calc_limits(). */
403
c_width = min((unsigned int) crop->width, width * 16);
404
c_height = min((unsigned int) crop->height, height * 16);
405
406
geo->width = width;
407
geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
408
/* Even to store Cb first, odd for Cr. */
409
geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
410
411
geo->sheight = c_height;
412
geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
413
sr = c_height >> !both_fields;
414
sr = (sr * 512U + (height >> 1)) / height - 512;
415
geo->vscale = (0x10000UL - sr) & 0x1fff;
416
geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
417
geo->vtotal = tvnorm->vtotal;
418
419
geo->crop = (((geo->width >> 8) & 0x03) |
420
((geo->hdelay >> 6) & 0x0c) |
421
((geo->sheight >> 4) & 0x30) |
422
((geo->vdelay >> 2) & 0xc0));
423
424
if (btv->opt_combfilter) {
425
geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
426
geo->comb = (width < 769) ? 1 : 0;
427
} else {
428
geo->vtc = 0;
429
geo->comb = 0;
430
}
431
}
432
433
static void
434
bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
435
{
436
int off = odd ? 0x80 : 0x00;
437
438
if (geo->comb)
439
btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
440
else
441
btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
442
443
btwrite(geo->vtc, BT848_E_VTC+off);
444
btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off);
445
btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off);
446
btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
447
btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off);
448
btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off);
449
btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off);
450
btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off);
451
btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off);
452
btwrite(geo->crop, BT848_E_CROP+off);
453
btwrite(geo->vtotal>>8, BT848_VTOTAL_HI);
454
btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO);
455
}
456
457
/* ---------------------------------------------------------- */
458
/* risc group / risc main loop / dma management */
459
460
void
461
bttv_set_dma(struct bttv *btv, int override)
462
{
463
unsigned long cmd;
464
int capctl;
465
466
btv->cap_ctl = 0;
467
if (NULL != btv->curr.top) btv->cap_ctl |= 0x02;
468
if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01;
469
if (NULL != btv->cvbi) btv->cap_ctl |= 0x0c;
470
471
capctl = 0;
472
capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */
473
capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00; /* vbi data */
474
capctl |= override;
475
476
d2printk(KERN_DEBUG
477
"bttv%d: capctl=%x lirq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
478
btv->c.nr,capctl,btv->loop_irq,
479
btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
480
btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
481
btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0,
482
btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
483
484
cmd = BT848_RISC_JUMP;
485
if (btv->loop_irq) {
486
cmd |= BT848_RISC_IRQ;
487
cmd |= (btv->loop_irq & 0x0f) << 16;
488
cmd |= (~btv->loop_irq & 0x0f) << 20;
489
}
490
if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
491
mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
492
} else {
493
del_timer(&btv->timeout);
494
}
495
btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
496
497
btaor(capctl, ~0x0f, BT848_CAP_CTL);
498
if (capctl) {
499
if (btv->dma_on)
500
return;
501
btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
502
btor(3, BT848_GPIO_DMA_CTL);
503
btv->dma_on = 1;
504
} else {
505
if (!btv->dma_on)
506
return;
507
btand(~3, BT848_GPIO_DMA_CTL);
508
btv->dma_on = 0;
509
}
510
return;
511
}
512
513
int
514
bttv_risc_init_main(struct bttv *btv)
515
{
516
int rc;
517
518
if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
519
return rc;
520
dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",
521
btv->c.nr,(unsigned long long)btv->main.dma);
522
523
btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
524
BT848_FIFO_STATUS_VRE);
525
btv->main.cpu[1] = cpu_to_le32(0);
526
btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
527
btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
528
529
/* top field */
530
btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
531
btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
532
btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
533
btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
534
535
btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
536
BT848_FIFO_STATUS_VRO);
537
btv->main.cpu[9] = cpu_to_le32(0);
538
539
/* bottom field */
540
btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
541
btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
542
btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
543
btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
544
545
/* jump back to top field */
546
btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
547
btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
548
549
return 0;
550
}
551
552
int
553
bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
554
int irqflags)
555
{
556
unsigned long cmd;
557
unsigned long next = btv->main.dma + ((slot+2) << 2);
558
559
if (NULL == risc) {
560
d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n",
561
btv->c.nr,risc,slot);
562
btv->main.cpu[slot+1] = cpu_to_le32(next);
563
} else {
564
d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n",
565
btv->c.nr,risc,slot,(unsigned long long)risc->dma,irqflags);
566
cmd = BT848_RISC_JUMP;
567
if (irqflags) {
568
cmd |= BT848_RISC_IRQ;
569
cmd |= (irqflags & 0x0f) << 16;
570
cmd |= (~irqflags & 0x0f) << 20;
571
}
572
risc->jmp[0] = cpu_to_le32(cmd);
573
risc->jmp[1] = cpu_to_le32(next);
574
btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
575
}
576
return 0;
577
}
578
579
void
580
bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
581
{
582
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
583
584
BUG_ON(in_interrupt());
585
videobuf_waiton(q, &buf->vb, 0, 0);
586
videobuf_dma_unmap(q->dev, dma);
587
videobuf_dma_free(dma);
588
btcx_riscmem_free(btv->c.pci,&buf->bottom);
589
btcx_riscmem_free(btv->c.pci,&buf->top);
590
buf->vb.state = VIDEOBUF_NEEDS_INIT;
591
}
592
593
int
594
bttv_buffer_activate_vbi(struct bttv *btv,
595
struct bttv_buffer *vbi)
596
{
597
struct btcx_riscmem *top;
598
struct btcx_riscmem *bottom;
599
int top_irq_flags;
600
int bottom_irq_flags;
601
602
top = NULL;
603
bottom = NULL;
604
top_irq_flags = 0;
605
bottom_irq_flags = 0;
606
607
if (vbi) {
608
unsigned int crop, vdelay;
609
610
vbi->vb.state = VIDEOBUF_ACTIVE;
611
list_del(&vbi->vb.queue);
612
613
/* VDELAY is start of video, end of VBI capturing. */
614
crop = btread(BT848_E_CROP);
615
vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
616
617
if (vbi->geo.vdelay > vdelay) {
618
vdelay = vbi->geo.vdelay & 0xfe;
619
crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
620
621
btwrite(vdelay, BT848_E_VDELAY_LO);
622
btwrite(crop, BT848_E_CROP);
623
btwrite(vdelay, BT848_O_VDELAY_LO);
624
btwrite(crop, BT848_O_CROP);
625
}
626
627
if (vbi->vbi_count[0] > 0) {
628
top = &vbi->top;
629
top_irq_flags = 4;
630
}
631
632
if (vbi->vbi_count[1] > 0) {
633
top_irq_flags = 0;
634
bottom = &vbi->bottom;
635
bottom_irq_flags = 4;
636
}
637
}
638
639
bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
640
bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
641
642
return 0;
643
}
644
645
int
646
bttv_buffer_activate_video(struct bttv *btv,
647
struct bttv_buffer_set *set)
648
{
649
/* video capture */
650
if (NULL != set->top && NULL != set->bottom) {
651
if (set->top == set->bottom) {
652
set->top->vb.state = VIDEOBUF_ACTIVE;
653
if (set->top->vb.queue.next)
654
list_del(&set->top->vb.queue);
655
} else {
656
set->top->vb.state = VIDEOBUF_ACTIVE;
657
set->bottom->vb.state = VIDEOBUF_ACTIVE;
658
if (set->top->vb.queue.next)
659
list_del(&set->top->vb.queue);
660
if (set->bottom->vb.queue.next)
661
list_del(&set->bottom->vb.queue);
662
}
663
bttv_apply_geo(btv, &set->top->geo, 1);
664
bttv_apply_geo(btv, &set->bottom->geo,0);
665
bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
666
set->top_irq);
667
bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
668
set->frame_irq);
669
btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
670
~0xff, BT848_COLOR_FMT);
671
btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
672
~0x0f, BT848_COLOR_CTL);
673
} else if (NULL != set->top) {
674
set->top->vb.state = VIDEOBUF_ACTIVE;
675
if (set->top->vb.queue.next)
676
list_del(&set->top->vb.queue);
677
bttv_apply_geo(btv, &set->top->geo,1);
678
bttv_apply_geo(btv, &set->top->geo,0);
679
bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
680
set->frame_irq);
681
bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
682
btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
683
btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
684
} else if (NULL != set->bottom) {
685
set->bottom->vb.state = VIDEOBUF_ACTIVE;
686
if (set->bottom->vb.queue.next)
687
list_del(&set->bottom->vb.queue);
688
bttv_apply_geo(btv, &set->bottom->geo,1);
689
bttv_apply_geo(btv, &set->bottom->geo,0);
690
bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
691
bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
692
set->frame_irq);
693
btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
694
btaor(set->bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
695
} else {
696
bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
697
bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
698
}
699
return 0;
700
}
701
702
/* ---------------------------------------------------------- */
703
704
/* calculate geometry, build risc code */
705
int
706
bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
707
{
708
const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
709
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
710
711
dprintk(KERN_DEBUG
712
"bttv%d: buffer field: %s format: %s size: %dx%d\n",
713
btv->c.nr, v4l2_field_names[buf->vb.field],
714
buf->fmt->name, buf->vb.width, buf->vb.height);
715
716
/* packed pixel modes */
717
if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
718
int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
719
int bpf = bpl * (buf->vb.height >> 1);
720
721
bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
722
V4L2_FIELD_HAS_BOTH(buf->vb.field),
723
tvnorm,&buf->crop);
724
725
switch (buf->vb.field) {
726
case V4L2_FIELD_TOP:
727
bttv_risc_packed(btv,&buf->top,dma->sglist,
728
/* offset */ 0,bpl,
729
/* padding */ 0,/* skip_lines */ 0,
730
buf->vb.height);
731
break;
732
case V4L2_FIELD_BOTTOM:
733
bttv_risc_packed(btv,&buf->bottom,dma->sglist,
734
0,bpl,0,0,buf->vb.height);
735
break;
736
case V4L2_FIELD_INTERLACED:
737
bttv_risc_packed(btv,&buf->top,dma->sglist,
738
0,bpl,bpl,0,buf->vb.height >> 1);
739
bttv_risc_packed(btv,&buf->bottom,dma->sglist,
740
bpl,bpl,bpl,0,buf->vb.height >> 1);
741
break;
742
case V4L2_FIELD_SEQ_TB:
743
bttv_risc_packed(btv,&buf->top,dma->sglist,
744
0,bpl,0,0,buf->vb.height >> 1);
745
bttv_risc_packed(btv,&buf->bottom,dma->sglist,
746
bpf,bpl,0,0,buf->vb.height >> 1);
747
break;
748
default:
749
BUG();
750
}
751
}
752
753
/* planar modes */
754
if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
755
int uoffset, voffset;
756
int ypadding, cpadding, lines;
757
758
/* calculate chroma offsets */
759
uoffset = buf->vb.width * buf->vb.height;
760
voffset = buf->vb.width * buf->vb.height;
761
if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
762
/* Y-Cr-Cb plane order */
763
uoffset >>= buf->fmt->hshift;
764
uoffset >>= buf->fmt->vshift;
765
uoffset += voffset;
766
} else {
767
/* Y-Cb-Cr plane order */
768
voffset >>= buf->fmt->hshift;
769
voffset >>= buf->fmt->vshift;
770
voffset += uoffset;
771
}
772
773
switch (buf->vb.field) {
774
case V4L2_FIELD_TOP:
775
bttv_calc_geo(btv,&buf->geo,buf->vb.width,
776
buf->vb.height,/* both_fields */ 0,
777
tvnorm,&buf->crop);
778
bttv_risc_planar(btv, &buf->top, dma->sglist,
779
0,buf->vb.width,0,buf->vb.height,
780
uoffset,voffset,buf->fmt->hshift,
781
buf->fmt->vshift,0);
782
break;
783
case V4L2_FIELD_BOTTOM:
784
bttv_calc_geo(btv,&buf->geo,buf->vb.width,
785
buf->vb.height,0,
786
tvnorm,&buf->crop);
787
bttv_risc_planar(btv, &buf->bottom, dma->sglist,
788
0,buf->vb.width,0,buf->vb.height,
789
uoffset,voffset,buf->fmt->hshift,
790
buf->fmt->vshift,0);
791
break;
792
case V4L2_FIELD_INTERLACED:
793
bttv_calc_geo(btv,&buf->geo,buf->vb.width,
794
buf->vb.height,1,
795
tvnorm,&buf->crop);
796
lines = buf->vb.height >> 1;
797
ypadding = buf->vb.width;
798
cpadding = buf->vb.width >> buf->fmt->hshift;
799
bttv_risc_planar(btv,&buf->top,
800
dma->sglist,
801
0,buf->vb.width,ypadding,lines,
802
uoffset,voffset,
803
buf->fmt->hshift,
804
buf->fmt->vshift,
805
cpadding);
806
bttv_risc_planar(btv,&buf->bottom,
807
dma->sglist,
808
ypadding,buf->vb.width,ypadding,lines,
809
uoffset+cpadding,
810
voffset+cpadding,
811
buf->fmt->hshift,
812
buf->fmt->vshift,
813
cpadding);
814
break;
815
case V4L2_FIELD_SEQ_TB:
816
bttv_calc_geo(btv,&buf->geo,buf->vb.width,
817
buf->vb.height,1,
818
tvnorm,&buf->crop);
819
lines = buf->vb.height >> 1;
820
ypadding = buf->vb.width;
821
cpadding = buf->vb.width >> buf->fmt->hshift;
822
bttv_risc_planar(btv,&buf->top,
823
dma->sglist,
824
0,buf->vb.width,0,lines,
825
uoffset >> 1,
826
voffset >> 1,
827
buf->fmt->hshift,
828
buf->fmt->vshift,
829
0);
830
bttv_risc_planar(btv,&buf->bottom,
831
dma->sglist,
832
lines * ypadding,buf->vb.width,0,lines,
833
lines * ypadding + (uoffset >> 1),
834
lines * ypadding + (voffset >> 1),
835
buf->fmt->hshift,
836
buf->fmt->vshift,
837
0);
838
break;
839
default:
840
BUG();
841
}
842
}
843
844
/* raw data */
845
if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
846
/* build risc code */
847
buf->vb.field = V4L2_FIELD_SEQ_TB;
848
bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
849
1,tvnorm,&buf->crop);
850
bttv_risc_packed(btv, &buf->top, dma->sglist,
851
/* offset */ 0, RAW_BPL, /* padding */ 0,
852
/* skip_lines */ 0, RAW_LINES);
853
bttv_risc_packed(btv, &buf->bottom, dma->sglist,
854
buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
855
}
856
857
/* copy format info */
858
buf->btformat = buf->fmt->btformat;
859
buf->btswap = buf->fmt->btswap;
860
return 0;
861
}
862
863
/* ---------------------------------------------------------- */
864
865
/* calculate geometry, build risc code */
866
int
867
bttv_overlay_risc(struct bttv *btv,
868
struct bttv_overlay *ov,
869
const struct bttv_format *fmt,
870
struct bttv_buffer *buf)
871
{
872
/* check interleave, bottom+top fields */
873
dprintk(KERN_DEBUG
874
"bttv%d: overlay fields: %s format: %s size: %dx%d\n",
875
btv->c.nr, v4l2_field_names[buf->vb.field],
876
fmt->name,ov->w.width,ov->w.height);
877
878
/* calculate geometry */
879
bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
880
V4L2_FIELD_HAS_BOTH(ov->field),
881
&bttv_tvnorms[ov->tvnorm],&buf->crop);
882
883
/* build risc code */
884
switch (ov->field) {
885
case V4L2_FIELD_TOP:
886
bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 0);
887
break;
888
case V4L2_FIELD_BOTTOM:
889
bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
890
break;
891
case V4L2_FIELD_INTERLACED:
892
bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 1);
893
bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
894
break;
895
default:
896
BUG();
897
}
898
899
/* copy format info */
900
buf->btformat = fmt->btformat;
901
buf->btswap = fmt->btswap;
902
buf->vb.field = ov->field;
903
return 0;
904
}
905
906
/*
907
* Local variables:
908
* c-basic-offset: 8
909
* End:
910
*/
911
912