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 ((line >= (store_lines - VCR_HACK_LINES)) &&
71 btv->opt_vcr_hack)
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 WARN_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 WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
231 return 0;
232 }
233
234 /* ---------------------------------------------------------- */
235
236 static void
bttv_calc_geo_old(struct bttv * btv,struct bttv_geometry * geo,int width,int height,int interleaved,const struct bttv_tvnorm * tvnorm)237 bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
238 int width, int height, int interleaved,
239 const struct bttv_tvnorm *tvnorm)
240 {
241 u32 xsf, sr;
242 int vdelay;
243
244 int swidth = tvnorm->swidth;
245 int totalwidth = tvnorm->totalwidth;
246 int scaledtwidth = tvnorm->scaledtwidth;
247
248 if (btv->input == btv->dig) {
249 swidth = 720;
250 totalwidth = 858;
251 scaledtwidth = 858;
252 }
253
254 vdelay = tvnorm->vdelay;
255
256 xsf = (width*scaledtwidth)/swidth;
257 geo->hscale = ((totalwidth*4096UL)/xsf-4096);
258 geo->hdelay = tvnorm->hdelayx1;
259 geo->hdelay = (geo->hdelay*width)/swidth;
260 geo->hdelay &= 0x3fe;
261 sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
262 geo->vscale = (0x10000UL-sr) & 0x1fff;
263 geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
264 ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
265 geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
266 geo->vdelay = vdelay;
267 geo->width = width;
268 geo->sheight = tvnorm->sheight;
269 geo->vtotal = tvnorm->vtotal;
270
271 if (btv->opt_combfilter) {
272 geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
273 geo->comb = (width < 769) ? 1 : 0;
274 } else {
275 geo->vtc = 0;
276 geo->comb = 0;
277 }
278 }
279
280 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)281 bttv_calc_geo (struct bttv * btv,
282 struct bttv_geometry * geo,
283 unsigned int width,
284 unsigned int height,
285 int both_fields,
286 const struct bttv_tvnorm * tvnorm,
287 const struct v4l2_rect * crop)
288 {
289 unsigned int c_width;
290 unsigned int c_height;
291 u32 sr;
292
293 if ((crop->left == tvnorm->cropcap.defrect.left
294 && crop->top == tvnorm->cropcap.defrect.top
295 && crop->width == tvnorm->cropcap.defrect.width
296 && crop->height == tvnorm->cropcap.defrect.height
297 && width <= tvnorm->swidth /* see PAL-Nc et al */)
298 || btv->input == btv->dig) {
299 bttv_calc_geo_old(btv, geo, width, height,
300 both_fields, tvnorm);
301 return;
302 }
303
304 /* For bug compatibility the image size checks permit scale
305 factors > 16. See bttv_crop_calc_limits(). */
306 c_width = min((unsigned int) crop->width, width * 16);
307 c_height = min((unsigned int) crop->height, height * 16);
308
309 geo->width = width;
310 geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
311 /* Even to store Cb first, odd for Cr. */
312 geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
313
314 geo->sheight = c_height;
315 geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
316 sr = c_height >> !both_fields;
317 sr = (sr * 512U + (height >> 1)) / height - 512;
318 geo->vscale = (0x10000UL - sr) & 0x1fff;
319 geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
320 geo->vtotal = tvnorm->vtotal;
321
322 geo->crop = (((geo->width >> 8) & 0x03) |
323 ((geo->hdelay >> 6) & 0x0c) |
324 ((geo->sheight >> 4) & 0x30) |
325 ((geo->vdelay >> 2) & 0xc0));
326
327 if (btv->opt_combfilter) {
328 geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
329 geo->comb = (width < 769) ? 1 : 0;
330 } else {
331 geo->vtc = 0;
332 geo->comb = 0;
333 }
334 }
335
336 static void
bttv_apply_geo(struct bttv * btv,struct bttv_geometry * geo,int odd)337 bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
338 {
339 int off = odd ? 0x80 : 0x00;
340
341 if (geo->comb)
342 btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
343 else
344 btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
345
346 btwrite(geo->vtc, BT848_E_VTC+off);
347 btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off);
348 btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off);
349 btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
350 btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off);
351 btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off);
352 btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off);
353 btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off);
354 btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off);
355 btwrite(geo->crop, BT848_E_CROP+off);
356 btwrite(geo->vtotal>>8, BT848_VTOTAL_HI);
357 btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO);
358 }
359
360 /* ---------------------------------------------------------- */
361 /* risc group / risc main loop / dma management */
362
bttv_set_risc_status(struct bttv * btv)363 static void bttv_set_risc_status(struct bttv *btv)
364 {
365 unsigned long cmd = BT848_RISC_JUMP;
366 if (btv->loop_irq) {
367 cmd |= BT848_RISC_IRQ;
368 cmd |= (btv->loop_irq & 0x0f) << 16;
369 cmd |= (~btv->loop_irq & 0x0f) << 20;
370 }
371 btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
372 }
373
bttv_set_irq_timer(struct bttv * btv)374 static void bttv_set_irq_timer(struct bttv *btv)
375 {
376 if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi)
377 mod_timer(&btv->timeout, jiffies + BTTV_TIMEOUT);
378 else
379 del_timer(&btv->timeout);
380 }
381
bttv_set_capture_control(struct bttv * btv,int start_capture)382 static int bttv_set_capture_control(struct bttv *btv, int start_capture)
383 {
384 int capctl = 0;
385
386 if (btv->curr.top || btv->curr.bottom)
387 capctl = BT848_CAP_CTL_CAPTURE_ODD |
388 BT848_CAP_CTL_CAPTURE_EVEN;
389
390 if (btv->cvbi)
391 capctl |= BT848_CAP_CTL_CAPTURE_VBI_ODD |
392 BT848_CAP_CTL_CAPTURE_VBI_EVEN;
393
394 capctl |= start_capture;
395
396 btaor(capctl, ~0x0f, BT848_CAP_CTL);
397
398 return capctl;
399 }
400
bttv_start_dma(struct bttv * btv)401 static void bttv_start_dma(struct bttv *btv)
402 {
403 if (btv->dma_on)
404 return;
405 btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
406 btor(BT848_GPIO_DMA_CTL_RISC_ENABLE | BT848_GPIO_DMA_CTL_FIFO_ENABLE,
407 BT848_GPIO_DMA_CTL);
408 btv->dma_on = 1;
409 }
410
bttv_stop_dma(struct bttv * btv)411 static void bttv_stop_dma(struct bttv *btv)
412 {
413 if (!btv->dma_on)
414 return;
415 btand(~(BT848_GPIO_DMA_CTL_RISC_ENABLE |
416 BT848_GPIO_DMA_CTL_FIFO_ENABLE), BT848_GPIO_DMA_CTL);
417 btv->dma_on = 0;
418 }
419
bttv_set_dma(struct bttv * btv,int start_capture)420 void bttv_set_dma(struct bttv *btv, int start_capture)
421 {
422 int capctl = 0;
423
424 bttv_set_risc_status(btv);
425 bttv_set_irq_timer(btv);
426 capctl = bttv_set_capture_control(btv, start_capture);
427
428 if (capctl)
429 bttv_start_dma(btv);
430 else
431 bttv_stop_dma(btv);
432
433 d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
434 btv->c.nr,capctl,btv->loop_irq,
435 btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
436 btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
437 btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0,
438 btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
439 }
440
441 int
bttv_risc_init_main(struct bttv * btv)442 bttv_risc_init_main(struct bttv *btv)
443 {
444 int rc;
445
446 if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
447 return rc;
448 dprintk("%d: risc main @ %08llx\n",
449 btv->c.nr, (unsigned long long)btv->main.dma);
450
451 btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
452 BT848_FIFO_STATUS_VRE);
453 btv->main.cpu[1] = cpu_to_le32(0);
454 btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
455 btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
456
457 /* top field */
458 btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
459 btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
460 btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
461 btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
462
463 btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
464 BT848_FIFO_STATUS_VRO);
465 btv->main.cpu[9] = cpu_to_le32(0);
466
467 /* bottom field */
468 btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
469 btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
470 btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
471 btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
472
473 /* jump back to top field */
474 btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
475 btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
476
477 return 0;
478 }
479
480 int
bttv_risc_hook(struct bttv * btv,int slot,struct btcx_riscmem * risc,int irqflags)481 bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
482 int irqflags)
483 {
484 unsigned long cmd;
485 unsigned long next = btv->main.dma + ((slot+2) << 2);
486
487 if (NULL == risc) {
488 d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
489 btv->main.cpu[slot+1] = cpu_to_le32(next);
490 } else {
491 d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
492 btv->c.nr, risc, slot,
493 (unsigned long long)risc->dma, irqflags);
494 cmd = BT848_RISC_JUMP;
495 if (irqflags) {
496 cmd |= BT848_RISC_IRQ;
497 cmd |= (irqflags & 0x0f) << 16;
498 cmd |= (~irqflags & 0x0f) << 20;
499 }
500 risc->jmp[0] = cpu_to_le32(cmd);
501 risc->jmp[1] = cpu_to_le32(next);
502 btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
503 }
504 return 0;
505 }
506
bttv_buffer_risc_vbi(struct bttv * btv,struct bttv_buffer * buf)507 int bttv_buffer_risc_vbi(struct bttv *btv, struct bttv_buffer *buf)
508 {
509 int r = 0;
510 unsigned int offset;
511 unsigned int bpl = 2044; /* max. vbipack */
512 unsigned int padding = VBI_BPL - bpl;
513 unsigned int skip_lines0 = 0;
514 unsigned int skip_lines1 = 0;
515 unsigned int min_vdelay = MIN_VDELAY;
516
517 const struct bttv_tvnorm *tvnorm = btv->vbi_fmt.tvnorm;
518 struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);
519 struct scatterlist *list = sgt->sgl;
520
521 if (btv->vbi_fmt.fmt.count[0] > 0)
522 skip_lines0 = max(0, (btv->vbi_fmt.fmt.start[0] -
523 tvnorm->vbistart[0]));
524 if (btv->vbi_fmt.fmt.count[1] > 0)
525 skip_lines1 = max(0, (btv->vbi_fmt.fmt.start[1] -
526 tvnorm->vbistart[1]));
527
528 if (btv->vbi_fmt.fmt.count[0] > 0) {
529 r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, padding,
530 skip_lines0, btv->vbi_fmt.fmt.count[0]);
531 if (r)
532 return r;
533 }
534
535 if (btv->vbi_fmt.fmt.count[1] > 0) {
536 offset = btv->vbi_fmt.fmt.count[0] * VBI_BPL;
537 r = bttv_risc_packed(btv, &buf->bottom, list, offset, bpl,
538 padding, skip_lines1,
539 btv->vbi_fmt.fmt.count[1]);
540 if (r)
541 return r;
542 }
543
544 if (btv->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
545 min_vdelay += btv->vbi_fmt.end - tvnorm->cropcap.bounds.top;
546
547 /* For bttv_buffer_activate_vbi(). */
548 buf->geo.vdelay = min_vdelay;
549
550 return r;
551 }
552
553 int
bttv_buffer_activate_vbi(struct bttv * btv,struct bttv_buffer * vbi)554 bttv_buffer_activate_vbi(struct bttv *btv,
555 struct bttv_buffer *vbi)
556 {
557 struct btcx_riscmem *top;
558 struct btcx_riscmem *bottom;
559 int top_irq_flags;
560 int bottom_irq_flags;
561
562 top = NULL;
563 bottom = NULL;
564 top_irq_flags = 0;
565 bottom_irq_flags = 0;
566
567 if (vbi) {
568 unsigned int crop, vdelay;
569
570 list_del(&vbi->list);
571
572 /* VDELAY is start of video, end of VBI capturing. */
573 crop = btread(BT848_E_CROP);
574 vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
575
576 if (vbi->geo.vdelay > vdelay) {
577 vdelay = vbi->geo.vdelay & 0xfe;
578 crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
579
580 btwrite(vdelay, BT848_E_VDELAY_LO);
581 btwrite(crop, BT848_E_CROP);
582 btwrite(vdelay, BT848_O_VDELAY_LO);
583 btwrite(crop, BT848_O_CROP);
584 }
585
586 if (btv->vbi_count[0] > 0) {
587 top = &vbi->top;
588 top_irq_flags = 4;
589 }
590
591 if (btv->vbi_count[1] > 0) {
592 top_irq_flags = 0;
593 bottom = &vbi->bottom;
594 bottom_irq_flags = 4;
595 }
596 }
597
598 bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
599 bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
600
601 return 0;
602 }
603
604 int
bttv_buffer_activate_video(struct bttv * btv,struct bttv_buffer_set * set)605 bttv_buffer_activate_video(struct bttv *btv,
606 struct bttv_buffer_set *set)
607 {
608 /* video capture */
609 if (NULL != set->top && NULL != set->bottom) {
610 if (set->top == set->bottom) {
611 if (set->top->list.next)
612 list_del(&set->top->list);
613 } else {
614 if (set->top->list.next)
615 list_del(&set->top->list);
616 if (set->bottom->list.next)
617 list_del(&set->bottom->list);
618 }
619 bttv_apply_geo(btv, &set->top->geo, 1);
620 bttv_apply_geo(btv, &set->bottom->geo,0);
621 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
622 set->top_irq);
623 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
624 set->frame_irq);
625 btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
626 ~0xff, BT848_COLOR_FMT);
627 btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
628 ~0x0f, BT848_COLOR_CTL);
629 } else if (NULL != set->top) {
630 if (set->top->list.next)
631 list_del(&set->top->list);
632 bttv_apply_geo(btv, &set->top->geo,1);
633 bttv_apply_geo(btv, &set->top->geo,0);
634 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
635 set->frame_irq);
636 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
637 btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
638 btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
639 } else if (NULL != set->bottom) {
640 if (set->bottom->list.next)
641 list_del(&set->bottom->list);
642 bttv_apply_geo(btv, &set->bottom->geo,1);
643 bttv_apply_geo(btv, &set->bottom->geo,0);
644 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
645 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
646 set->frame_irq);
647 btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
648 btaor(set->bottom->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
649 } else {
650 bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
651 bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
652 }
653 return 0;
654 }
655
656 /* ---------------------------------------------------------- */
657
658 /* calculate geometry, build risc code */
659 int
bttv_buffer_risc(struct bttv * btv,struct bttv_buffer * buf)660 bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
661 {
662 int r = 0;
663 const struct bttv_tvnorm *tvnorm = bttv_tvnorms + btv->tvnorm;
664 struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);
665 struct scatterlist *list = sgt->sgl;
666 unsigned long size = (btv->fmt->depth * btv->width * btv->height) >> 3;
667
668 /* packed pixel modes */
669 if (btv->fmt->flags & FORMAT_FLAGS_PACKED) {
670 int bpl = (btv->fmt->depth >> 3) * btv->width;
671 int bpf = bpl * (btv->height >> 1);
672
673 bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
674 V4L2_FIELD_HAS_BOTH(buf->vbuf.field), tvnorm,
675 &btv->crop[!!btv->do_crop].rect);
676 switch (buf->vbuf.field) {
677 case V4L2_FIELD_TOP:
678 r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
679 0, btv->height);
680 break;
681 case V4L2_FIELD_BOTTOM:
682 r = bttv_risc_packed(btv, &buf->bottom, list, 0, bpl,
683 0, 0, btv->height);
684 break;
685 case V4L2_FIELD_INTERLACED:
686 r = bttv_risc_packed(btv, &buf->top, list, 0, bpl,
687 bpl, 0, btv->height >> 1);
688 r = bttv_risc_packed(btv, &buf->bottom, list, bpl,
689 bpl, bpl, 0, btv->height >> 1);
690 break;
691 case V4L2_FIELD_SEQ_TB:
692 r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
693 0, btv->height >> 1);
694 r = bttv_risc_packed(btv, &buf->bottom, list, bpf,
695 bpl, 0, 0, btv->height >> 1);
696 break;
697 default:
698 WARN_ON(1);
699 return -EINVAL;
700 }
701 }
702 /* planar modes */
703 if (btv->fmt->flags & FORMAT_FLAGS_PLANAR) {
704 int uoffset, voffset;
705 int ypadding, cpadding, lines;
706
707 /* calculate chroma offsets */
708 uoffset = btv->width * btv->height;
709 voffset = btv->width * btv->height;
710 if (btv->fmt->flags & FORMAT_FLAGS_CrCb) {
711 /* Y-Cr-Cb plane order */
712 uoffset >>= btv->fmt->hshift;
713 uoffset >>= btv->fmt->vshift;
714 uoffset += voffset;
715 } else {
716 /* Y-Cb-Cr plane order */
717 voffset >>= btv->fmt->hshift;
718 voffset >>= btv->fmt->vshift;
719 voffset += uoffset;
720 }
721 switch (buf->vbuf.field) {
722 case V4L2_FIELD_TOP:
723 bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
724 0, tvnorm,
725 &btv->crop[!!btv->do_crop].rect);
726 r = bttv_risc_planar(btv, &buf->top, list, 0,
727 btv->width, 0, btv->height,
728 uoffset, voffset,
729 btv->fmt->hshift,
730 btv->fmt->vshift, 0);
731 break;
732 case V4L2_FIELD_BOTTOM:
733 bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
734 0, tvnorm,
735 &btv->crop[!!btv->do_crop].rect);
736 r = bttv_risc_planar(btv, &buf->bottom, list, 0,
737 btv->width, 0, btv->height,
738 uoffset, voffset,
739 btv->fmt->hshift,
740 btv->fmt->vshift, 0);
741 break;
742 case V4L2_FIELD_INTERLACED:
743 bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
744 1, tvnorm,
745 &btv->crop[!!btv->do_crop].rect);
746 lines = btv->height >> 1;
747 ypadding = btv->width;
748 cpadding = btv->width >> btv->fmt->hshift;
749 r = bttv_risc_planar(btv, &buf->top, list, 0,
750 btv->width, ypadding, lines,
751 uoffset, voffset,
752 btv->fmt->hshift,
753 btv->fmt->vshift, cpadding);
754
755 r = bttv_risc_planar(btv, &buf->bottom, list,
756 ypadding, btv->width, ypadding,
757 lines, uoffset + cpadding,
758 voffset + cpadding,
759 btv->fmt->hshift,
760 btv->fmt->vshift, cpadding);
761 break;
762 case V4L2_FIELD_SEQ_TB:
763 bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
764 1, tvnorm,
765 &btv->crop[!!btv->do_crop].rect);
766 lines = btv->height >> 1;
767 ypadding = btv->width;
768 cpadding = btv->width >> btv->fmt->hshift;
769 r = bttv_risc_planar(btv, &buf->top, list, 0,
770 btv->width, 0, lines,
771 uoffset >> 1, voffset >> 1,
772 btv->fmt->hshift,
773 btv->fmt->vshift, 0);
774 r = bttv_risc_planar(btv, &buf->bottom, list,
775 lines * ypadding,
776 btv->width, 0, lines,
777 lines * ypadding + (uoffset >> 1),
778 lines * ypadding + (voffset >> 1),
779 btv->fmt->hshift,
780 btv->fmt->vshift, 0);
781 break;
782 default:
783 WARN_ON(1);
784 return -EINVAL;
785 }
786 }
787 /* raw data */
788 if (btv->fmt->flags & FORMAT_FLAGS_RAW) {
789 /* build risc code */
790 buf->vbuf.field = V4L2_FIELD_SEQ_TB;
791 bttv_calc_geo(btv, &buf->geo, tvnorm->swidth, tvnorm->sheight,
792 1, tvnorm, &btv->crop[!!btv->do_crop].rect);
793 r = bttv_risc_packed(btv, &buf->top, list, 0, RAW_BPL, 0, 0,
794 RAW_LINES);
795 r = bttv_risc_packed(btv, &buf->bottom, list, size / 2,
796 RAW_BPL, 0, 0, RAW_LINES);
797 }
798
799 /* copy format info */
800 buf->btformat = btv->fmt->btformat;
801 buf->btswap = btv->fmt->btswap;
802
803 return r;
804 }
805