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