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