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