blob: 9ed21fd190c6cc24ed3e5fc5a57360956f77e8b6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
338 xsf = (width*scaledtwidth)/swidth;
339 geo->hscale = ((totalwidth*4096UL)/xsf-4096);
340 geo->hdelay = tvnorm->hdelayx1;
341 geo->hdelay = (geo->hdelay*width)/swidth;
342 geo->hdelay &= 0x3fe;
343 sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
344 geo->vscale = (0x10000UL-sr) & 0x1fff;
345 geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
346 ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
347 geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
348 geo->vdelay = vdelay;
349 geo->width = width;
350 geo->sheight = tvnorm->sheight;
351 geo->vtotal = tvnorm->vtotal;
352
353 if (btv->opt_combfilter) {
354 geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
355 geo->comb = (width < 769) ? 1 : 0;
356 } else {
357 geo->vtc = 0;
358 geo->comb = 0;
359 }
360}
361
362static void
363bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
364{
365 int off = odd ? 0x80 : 0x00;
366
367 if (geo->comb)
368 btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
369 else
370 btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
371
372 btwrite(geo->vtc, BT848_E_VTC+off);
373 btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off);
374 btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off);
375 btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
376 btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off);
377 btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off);
378 btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off);
379 btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off);
380 btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off);
381 btwrite(geo->crop, BT848_E_CROP+off);
382 btwrite(geo->vtotal>>8, BT848_VTOTAL_HI);
383 btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO);
384}
385
386/* ---------------------------------------------------------- */
387/* risc group / risc main loop / dma management */
388
389void
390bttv_set_dma(struct bttv *btv, int override)
391{
392 unsigned long cmd;
393 int capctl;
394
395 btv->cap_ctl = 0;
396 if (NULL != btv->curr.top) btv->cap_ctl |= 0x02;
397 if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01;
398 if (NULL != btv->cvbi) btv->cap_ctl |= 0x0c;
399
400 capctl = 0;
401 capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */
402 capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00; /* vbi data */
403 capctl |= override;
404
405 d2printk(KERN_DEBUG
406 "bttv%d: capctl=%x lirq=%d top=%08Lx/%08Lx even=%08Lx/%08Lx\n",
407 btv->c.nr,capctl,btv->loop_irq,
408 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
409 btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
410 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0,
411 btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
412
413 cmd = BT848_RISC_JUMP;
414 if (btv->loop_irq) {
415 cmd |= BT848_RISC_IRQ;
416 cmd |= (btv->loop_irq & 0x0f) << 16;
417 cmd |= (~btv->loop_irq & 0x0f) << 20;
418 }
419 if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
420 mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
421 } else {
422 del_timer(&btv->timeout);
423 }
424 btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
425
426 btaor(capctl, ~0x0f, BT848_CAP_CTL);
427 if (capctl) {
428 if (btv->dma_on)
429 return;
430 btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
431 btor(3, BT848_GPIO_DMA_CTL);
432 btv->dma_on = 1;
433 } else {
434 if (!btv->dma_on)
435 return;
436 btand(~3, BT848_GPIO_DMA_CTL);
437 btv->dma_on = 0;
438 }
439 return;
440}
441
442int
443bttv_risc_init_main(struct bttv *btv)
444{
445 int rc;
446
447 if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
448 return rc;
449 dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",
450 btv->c.nr,(unsigned long long)btv->main.dma);
451
452 btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
453 BT848_FIFO_STATUS_VRE);
454 btv->main.cpu[1] = cpu_to_le32(0);
455 btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
456 btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
457
458 /* top field */
459 btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
460 btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
461 btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
462 btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
463
464 btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
465 BT848_FIFO_STATUS_VRO);
466 btv->main.cpu[9] = cpu_to_le32(0);
467
468 /* bottom field */
469 btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
470 btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
471 btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
472 btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
473
474 /* jump back to top field */
475 btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
476 btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
477
478 return 0;
479}
480
481int
482bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
483 int irqflags)
484{
485 unsigned long cmd;
486 unsigned long next = btv->main.dma + ((slot+2) << 2);
487
488 if (NULL == risc) {
489 d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=NULL\n",
490 btv->c.nr,risc,slot);
491 btv->main.cpu[slot+1] = cpu_to_le32(next);
492 } else {
493 d2printk(KERN_DEBUG "bttv%d: risc=%p slot[%d]=%08Lx irq=%d\n",
494 btv->c.nr,risc,slot,(unsigned long long)risc->dma,irqflags);
495 cmd = BT848_RISC_JUMP;
496 if (irqflags) {
497 cmd |= BT848_RISC_IRQ;
498 cmd |= (irqflags & 0x0f) << 16;
499 cmd |= (~irqflags & 0x0f) << 20;
500 }
501 risc->jmp[0] = cpu_to_le32(cmd);
502 risc->jmp[1] = cpu_to_le32(next);
503 btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
504 }
505 return 0;
506}
507
508void
509bttv_dma_free(struct bttv *btv, struct bttv_buffer *buf)
510{
511 if (in_interrupt())
512 BUG();
513 videobuf_waiton(&buf->vb,0,0);
514 videobuf_dma_pci_unmap(btv->c.pci, &buf->vb.dma);
515 videobuf_dma_free(&buf->vb.dma);
516 btcx_riscmem_free(btv->c.pci,&buf->bottom);
517 btcx_riscmem_free(btv->c.pci,&buf->top);
518 buf->vb.state = STATE_NEEDS_INIT;
519}
520
521int
522bttv_buffer_activate_vbi(struct bttv *btv,
523 struct bttv_buffer *vbi)
524{
525 /* vbi capture */
526 if (vbi) {
527 vbi->vb.state = STATE_ACTIVE;
528 list_del(&vbi->vb.queue);
529 bttv_risc_hook(btv, RISC_SLOT_O_VBI, &vbi->top, 0);
530 bttv_risc_hook(btv, RISC_SLOT_E_VBI, &vbi->bottom, 4);
531 } else {
532 bttv_risc_hook(btv, RISC_SLOT_O_VBI, NULL, 0);
533 bttv_risc_hook(btv, RISC_SLOT_E_VBI, NULL, 0);
534 }
535 return 0;
536}
537
538int
539bttv_buffer_activate_video(struct bttv *btv,
540 struct bttv_buffer_set *set)
541{
542 /* video capture */
543 if (NULL != set->top && NULL != set->bottom) {
544 if (set->top == set->bottom) {
545 set->top->vb.state = STATE_ACTIVE;
546 if (set->top->vb.queue.next)
547 list_del(&set->top->vb.queue);
548 } else {
549 set->top->vb.state = STATE_ACTIVE;
550 set->bottom->vb.state = STATE_ACTIVE;
551 if (set->top->vb.queue.next)
552 list_del(&set->top->vb.queue);
553 if (set->bottom->vb.queue.next)
554 list_del(&set->bottom->vb.queue);
555 }
556 bttv_apply_geo(btv, &set->top->geo, 1);
557 bttv_apply_geo(btv, &set->bottom->geo,0);
558 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
559 set->top_irq);
560 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
561 set->frame_irq);
562 btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
563 ~0xff, BT848_COLOR_FMT);
564 btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
565 ~0x0f, BT848_COLOR_CTL);
566 } else if (NULL != set->top) {
567 set->top->vb.state = STATE_ACTIVE;
568 if (set->top->vb.queue.next)
569 list_del(&set->top->vb.queue);
570 bttv_apply_geo(btv, &set->top->geo,1);
571 bttv_apply_geo(btv, &set->top->geo,0);
572 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
573 set->frame_irq);
574 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
575 btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
576 btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
577 } else if (NULL != set->bottom) {
578 set->bottom->vb.state = STATE_ACTIVE;
579 if (set->bottom->vb.queue.next)
580 list_del(&set->bottom->vb.queue);
581 bttv_apply_geo(btv, &set->bottom->geo,1);
582 bttv_apply_geo(btv, &set->bottom->geo,0);
583 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
584 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
585 set->frame_irq);
586 btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
587 btaor(set->bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
588 } else {
589 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
590 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
591 }
592 return 0;
593}
594
595/* ---------------------------------------------------------- */
596
597/* calculate geometry, build risc code */
598int
599bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
600{
601 const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
602
603 dprintk(KERN_DEBUG
604 "bttv%d: buffer field: %s format: %s size: %dx%d\n",
605 btv->c.nr, v4l2_field_names[buf->vb.field],
606 buf->fmt->name, buf->vb.width, buf->vb.height);
607
608 /* packed pixel modes */
609 if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
610 int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
611 int bpf = bpl * (buf->vb.height >> 1);
612
613 bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
614 V4L2_FIELD_HAS_BOTH(buf->vb.field),buf->tvnorm);
615
616 switch (buf->vb.field) {
617 case V4L2_FIELD_TOP:
618 bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
619 0,bpl,0,buf->vb.height);
620 break;
621 case V4L2_FIELD_BOTTOM:
622 bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
623 0,bpl,0,buf->vb.height);
624 break;
625 case V4L2_FIELD_INTERLACED:
626 bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
627 0,bpl,bpl,buf->vb.height >> 1);
628 bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
629 bpl,bpl,bpl,buf->vb.height >> 1);
630 break;
631 case V4L2_FIELD_SEQ_TB:
632 bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
633 0,bpl,0,buf->vb.height >> 1);
634 bttv_risc_packed(btv,&buf->bottom,buf->vb.dma.sglist,
635 bpf,bpl,0,buf->vb.height >> 1);
636 break;
637 default:
638 BUG();
639 }
640 }
641
642 /* planar modes */
643 if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
644 int uoffset, voffset;
645 int ypadding, cpadding, lines;
646
647 /* calculate chroma offsets */
648 uoffset = buf->vb.width * buf->vb.height;
649 voffset = buf->vb.width * buf->vb.height;
650 if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
651 /* Y-Cr-Cb plane order */
652 uoffset >>= buf->fmt->hshift;
653 uoffset >>= buf->fmt->vshift;
654 uoffset += voffset;
655 } else {
656 /* Y-Cb-Cr plane order */
657 voffset >>= buf->fmt->hshift;
658 voffset >>= buf->fmt->vshift;
659 voffset += uoffset;
660 }
661
662 switch (buf->vb.field) {
663 case V4L2_FIELD_TOP:
664 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
665 buf->vb.height,0,buf->tvnorm);
666 bttv_risc_planar(btv, &buf->top, buf->vb.dma.sglist,
667 0,buf->vb.width,0,buf->vb.height,
668 uoffset,voffset,buf->fmt->hshift,
669 buf->fmt->vshift,0);
670 break;
671 case V4L2_FIELD_BOTTOM:
672 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
673 buf->vb.height,0,buf->tvnorm);
674 bttv_risc_planar(btv, &buf->bottom, buf->vb.dma.sglist,
675 0,buf->vb.width,0,buf->vb.height,
676 uoffset,voffset,buf->fmt->hshift,
677 buf->fmt->vshift,0);
678 break;
679 case V4L2_FIELD_INTERLACED:
680 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
681 buf->vb.height,1,buf->tvnorm);
682 lines = buf->vb.height >> 1;
683 ypadding = buf->vb.width;
684 cpadding = buf->vb.width >> buf->fmt->hshift;
685 bttv_risc_planar(btv,&buf->top,
686 buf->vb.dma.sglist,
687 0,buf->vb.width,ypadding,lines,
688 uoffset,voffset,
689 buf->fmt->hshift,
690 buf->fmt->vshift,
691 cpadding);
692 bttv_risc_planar(btv,&buf->bottom,
693 buf->vb.dma.sglist,
694 ypadding,buf->vb.width,ypadding,lines,
695 uoffset+cpadding,
696 voffset+cpadding,
697 buf->fmt->hshift,
698 buf->fmt->vshift,
699 cpadding);
700 break;
701 case V4L2_FIELD_SEQ_TB:
702 bttv_calc_geo(btv,&buf->geo,buf->vb.width,
703 buf->vb.height,1,buf->tvnorm);
704 lines = buf->vb.height >> 1;
705 ypadding = buf->vb.width;
706 cpadding = buf->vb.width >> buf->fmt->hshift;
707 bttv_risc_planar(btv,&buf->top,
708 buf->vb.dma.sglist,
709 0,buf->vb.width,0,lines,
710 uoffset >> 1,
711 voffset >> 1,
712 buf->fmt->hshift,
713 buf->fmt->vshift,
714 0);
715 bttv_risc_planar(btv,&buf->bottom,
716 buf->vb.dma.sglist,
717 lines * ypadding,buf->vb.width,0,lines,
718 lines * ypadding + (uoffset >> 1),
719 lines * ypadding + (voffset >> 1),
720 buf->fmt->hshift,
721 buf->fmt->vshift,
722 0);
723 break;
724 default:
725 BUG();
726 }
727 }
728
729 /* raw data */
730 if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
731 /* build risc code */
732 buf->vb.field = V4L2_FIELD_SEQ_TB;
733 bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
734 1,buf->tvnorm);
735 bttv_risc_packed(btv, &buf->top, buf->vb.dma.sglist,
736 0, RAW_BPL, 0, RAW_LINES);
737 bttv_risc_packed(btv, &buf->bottom, buf->vb.dma.sglist,
738 buf->vb.size/2 , RAW_BPL, 0, RAW_LINES);
739 }
740
741 /* copy format info */
742 buf->btformat = buf->fmt->btformat;
743 buf->btswap = buf->fmt->btswap;
744 return 0;
745}
746
747/* ---------------------------------------------------------- */
748
749/* calculate geometry, build risc code */
750int
751bttv_overlay_risc(struct bttv *btv,
752 struct bttv_overlay *ov,
753 const struct bttv_format *fmt,
754 struct bttv_buffer *buf)
755{
756 /* check interleave, bottom+top fields */
757 dprintk(KERN_DEBUG
758 "bttv%d: overlay fields: %s format: %s size: %dx%d\n",
759 btv->c.nr, v4l2_field_names[buf->vb.field],
760 fmt->name,ov->w.width,ov->w.height);
761
762 /* calculate geometry */
763 bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
764 V4L2_FIELD_HAS_BOTH(ov->field), ov->tvnorm);
765
766 /* build risc code */
767 switch (ov->field) {
768 case V4L2_FIELD_TOP:
769 bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 0);
770 break;
771 case V4L2_FIELD_BOTTOM:
772 bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
773 break;
774 case V4L2_FIELD_INTERLACED:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 bttv_risc_overlay(btv, &buf->top, fmt, ov, 0, 1);
776 bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 break;
778 default:
779 BUG();
780 }
781
782 /* copy format info */
783 buf->btformat = fmt->btformat;
784 buf->btswap = fmt->btswap;
785 buf->vb.field = ov->field;
786 return 0;
787}
788
789/*
790 * Local variables:
791 * c-basic-offset: 8
792 * End:
793 */