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