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