linux/drivers/media/pci/bt8xx/bttv-risc.c
<<
>>
Prefs
   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 <asm/page.h>
  24#include <asm/pgtable.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
  34int
  35bttv_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
 113static int
 114bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
 115                 struct scatterlist *sglist,
 116                 unsigned int yoffset,  unsigned int ybpl,
 117                 unsigned int ypadding, unsigned int ylines,
 118                 unsigned int uoffset,  unsigned int voffset,
 119                 unsigned int hshift,   unsigned int vshift,
 120                 unsigned int cpadding)
 121{
 122        unsigned int instructions,line,todo,ylen,chroma;
 123        __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
 234static int
 235bttv_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
 325static void
 326bttv_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
 369static void
 370bttv_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
 425static void
 426bttv_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
 452void
 453bttv_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
 504int
 505bttv_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
 543int
 544bttv_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
 570void
 571bttv_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        BUG_ON(in_interrupt());
 576        videobuf_waiton(q, &buf->vb, 0, 0);
 577        videobuf_dma_unmap(q->dev, dma);
 578        videobuf_dma_free(dma);
 579        btcx_riscmem_free(btv->c.pci,&buf->bottom);
 580        btcx_riscmem_free(btv->c.pci,&buf->top);
 581        buf->vb.state = VIDEOBUF_NEEDS_INIT;
 582}
 583
 584int
 585bttv_buffer_activate_vbi(struct bttv *btv,
 586                         struct bttv_buffer *vbi)
 587{
 588        struct btcx_riscmem *top;
 589        struct btcx_riscmem *bottom;
 590        int top_irq_flags;
 591        int bottom_irq_flags;
 592
 593        top = NULL;
 594        bottom = NULL;
 595        top_irq_flags = 0;
 596        bottom_irq_flags = 0;
 597
 598        if (vbi) {
 599                unsigned int crop, vdelay;
 600
 601                vbi->vb.state = VIDEOBUF_ACTIVE;
 602                list_del(&vbi->vb.queue);
 603
 604                /* VDELAY is start of video, end of VBI capturing. */
 605                crop = btread(BT848_E_CROP);
 606                vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
 607
 608                if (vbi->geo.vdelay > vdelay) {
 609                        vdelay = vbi->geo.vdelay & 0xfe;
 610                        crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
 611
 612                        btwrite(vdelay, BT848_E_VDELAY_LO);
 613                        btwrite(crop,   BT848_E_CROP);
 614                        btwrite(vdelay, BT848_O_VDELAY_LO);
 615                        btwrite(crop,   BT848_O_CROP);
 616                }
 617
 618                if (vbi->vbi_count[0] > 0) {
 619                        top = &vbi->top;
 620                        top_irq_flags = 4;
 621                }
 622
 623                if (vbi->vbi_count[1] > 0) {
 624                        top_irq_flags = 0;
 625                        bottom = &vbi->bottom;
 626                        bottom_irq_flags = 4;
 627                }
 628        }
 629
 630        bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
 631        bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
 632
 633        return 0;
 634}
 635
 636int
 637bttv_buffer_activate_video(struct bttv *btv,
 638                           struct bttv_buffer_set *set)
 639{
 640        /* video capture */
 641        if (NULL != set->top  &&  NULL != set->bottom) {
 642                if (set->top == set->bottom) {
 643                        set->top->vb.state    = VIDEOBUF_ACTIVE;
 644                        if (set->top->vb.queue.next)
 645                                list_del(&set->top->vb.queue);
 646                } else {
 647                        set->top->vb.state    = VIDEOBUF_ACTIVE;
 648                        set->bottom->vb.state = VIDEOBUF_ACTIVE;
 649                        if (set->top->vb.queue.next)
 650                                list_del(&set->top->vb.queue);
 651                        if (set->bottom->vb.queue.next)
 652                                list_del(&set->bottom->vb.queue);
 653                }
 654                bttv_apply_geo(btv, &set->top->geo, 1);
 655                bttv_apply_geo(btv, &set->bottom->geo,0);
 656                bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
 657                               set->top_irq);
 658                bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
 659                               set->frame_irq);
 660                btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
 661                      ~0xff, BT848_COLOR_FMT);
 662                btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
 663                      ~0x0f, BT848_COLOR_CTL);
 664        } else if (NULL != set->top) {
 665                set->top->vb.state  = VIDEOBUF_ACTIVE;
 666                if (set->top->vb.queue.next)
 667                        list_del(&set->top->vb.queue);
 668                bttv_apply_geo(btv, &set->top->geo,1);
 669                bttv_apply_geo(btv, &set->top->geo,0);
 670                bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
 671                               set->frame_irq);
 672                bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
 673                btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
 674                btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
 675        } else if (NULL != set->bottom) {
 676                set->bottom->vb.state = VIDEOBUF_ACTIVE;
 677                if (set->bottom->vb.queue.next)
 678                        list_del(&set->bottom->vb.queue);
 679                bttv_apply_geo(btv, &set->bottom->geo,1);
 680                bttv_apply_geo(btv, &set->bottom->geo,0);
 681                bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
 682                bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
 683                               set->frame_irq);
 684                btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
 685                btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
 686        } else {
 687                bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
 688                bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
 689        }
 690        return 0;
 691}
 692
 693/* ---------------------------------------------------------- */
 694
 695/* calculate geometry, build risc code */
 696int
 697bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
 698{
 699        const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
 700        struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
 701
 702        dprintk("%d: buffer field: %s  format: %s  size: %dx%d\n",
 703                btv->c.nr, v4l2_field_names[buf->vb.field],
 704                buf->fmt->name, buf->vb.width, buf->vb.height);
 705
 706        /* packed pixel modes */
 707        if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
 708                int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
 709                int bpf = bpl * (buf->vb.height >> 1);
 710
 711                bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
 712                              V4L2_FIELD_HAS_BOTH(buf->vb.field),
 713                              tvnorm,&buf->crop);
 714
 715                switch (buf->vb.field) {
 716                case V4L2_FIELD_TOP:
 717                        bttv_risc_packed(btv,&buf->top,dma->sglist,
 718                                         /* offset */ 0,bpl,
 719                                         /* padding */ 0,/* skip_lines */ 0,
 720                                         buf->vb.height);
 721                        break;
 722                case V4L2_FIELD_BOTTOM:
 723                        bttv_risc_packed(btv,&buf->bottom,dma->sglist,
 724                                         0,bpl,0,0,buf->vb.height);
 725                        break;
 726                case V4L2_FIELD_INTERLACED:
 727                        bttv_risc_packed(btv,&buf->top,dma->sglist,
 728                                         0,bpl,bpl,0,buf->vb.height >> 1);
 729                        bttv_risc_packed(btv,&buf->bottom,dma->sglist,
 730                                         bpl,bpl,bpl,0,buf->vb.height >> 1);
 731                        break;
 732                case V4L2_FIELD_SEQ_TB:
 733                        bttv_risc_packed(btv,&buf->top,dma->sglist,
 734                                         0,bpl,0,0,buf->vb.height >> 1);
 735                        bttv_risc_packed(btv,&buf->bottom,dma->sglist,
 736                                         bpf,bpl,0,0,buf->vb.height >> 1);
 737                        break;
 738                default:
 739                        BUG();
 740                }
 741        }
 742
 743        /* planar modes */
 744        if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
 745                int uoffset, voffset;
 746                int ypadding, cpadding, lines;
 747
 748                /* calculate chroma offsets */
 749                uoffset = buf->vb.width * buf->vb.height;
 750                voffset = buf->vb.width * buf->vb.height;
 751                if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
 752                        /* Y-Cr-Cb plane order */
 753                        uoffset >>= buf->fmt->hshift;
 754                        uoffset >>= buf->fmt->vshift;
 755                        uoffset  += voffset;
 756                } else {
 757                        /* Y-Cb-Cr plane order */
 758                        voffset >>= buf->fmt->hshift;
 759                        voffset >>= buf->fmt->vshift;
 760                        voffset  += uoffset;
 761                }
 762
 763                switch (buf->vb.field) {
 764                case V4L2_FIELD_TOP:
 765                        bttv_calc_geo(btv,&buf->geo,buf->vb.width,
 766                                      buf->vb.height,/* both_fields */ 0,
 767                                      tvnorm,&buf->crop);
 768                        bttv_risc_planar(btv, &buf->top, dma->sglist,
 769                                         0,buf->vb.width,0,buf->vb.height,
 770                                         uoffset,voffset,buf->fmt->hshift,
 771                                         buf->fmt->vshift,0);
 772                        break;
 773                case V4L2_FIELD_BOTTOM:
 774                        bttv_calc_geo(btv,&buf->geo,buf->vb.width,
 775                                      buf->vb.height,0,
 776                                      tvnorm,&buf->crop);
 777                        bttv_risc_planar(btv, &buf->bottom, dma->sglist,
 778                                         0,buf->vb.width,0,buf->vb.height,
 779                                         uoffset,voffset,buf->fmt->hshift,
 780                                         buf->fmt->vshift,0);
 781                        break;
 782                case V4L2_FIELD_INTERLACED:
 783                        bttv_calc_geo(btv,&buf->geo,buf->vb.width,
 784                                      buf->vb.height,1,
 785                                      tvnorm,&buf->crop);
 786                        lines    = buf->vb.height >> 1;
 787                        ypadding = buf->vb.width;
 788                        cpadding = buf->vb.width >> buf->fmt->hshift;
 789                        bttv_risc_planar(btv,&buf->top,
 790                                         dma->sglist,
 791                                         0,buf->vb.width,ypadding,lines,
 792                                         uoffset,voffset,
 793                                         buf->fmt->hshift,
 794                                         buf->fmt->vshift,
 795                                         cpadding);
 796                        bttv_risc_planar(btv,&buf->bottom,
 797                                         dma->sglist,
 798                                         ypadding,buf->vb.width,ypadding,lines,
 799                                         uoffset+cpadding,
 800                                         voffset+cpadding,
 801                                         buf->fmt->hshift,
 802                                         buf->fmt->vshift,
 803                                         cpadding);
 804                        break;
 805                case V4L2_FIELD_SEQ_TB:
 806                        bttv_calc_geo(btv,&buf->geo,buf->vb.width,
 807                                      buf->vb.height,1,
 808                                      tvnorm,&buf->crop);
 809                        lines    = buf->vb.height >> 1;
 810                        ypadding = buf->vb.width;
 811                        cpadding = buf->vb.width >> buf->fmt->hshift;
 812                        bttv_risc_planar(btv,&buf->top,
 813                                         dma->sglist,
 814                                         0,buf->vb.width,0,lines,
 815                                         uoffset >> 1,
 816                                         voffset >> 1,
 817                                         buf->fmt->hshift,
 818                                         buf->fmt->vshift,
 819                                         0);
 820                        bttv_risc_planar(btv,&buf->bottom,
 821                                         dma->sglist,
 822                                         lines * ypadding,buf->vb.width,0,lines,
 823                                         lines * ypadding + (uoffset >> 1),
 824                                         lines * ypadding + (voffset >> 1),
 825                                         buf->fmt->hshift,
 826                                         buf->fmt->vshift,
 827                                         0);
 828                        break;
 829                default:
 830                        BUG();
 831                }
 832        }
 833
 834        /* raw data */
 835        if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
 836                /* build risc code */
 837                buf->vb.field = V4L2_FIELD_SEQ_TB;
 838                bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
 839                              1,tvnorm,&buf->crop);
 840                bttv_risc_packed(btv, &buf->top,  dma->sglist,
 841                                 /* offset */ 0, RAW_BPL, /* padding */ 0,
 842                                 /* skip_lines */ 0, RAW_LINES);
 843                bttv_risc_packed(btv, &buf->bottom, dma->sglist,
 844                                 buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
 845        }
 846
 847        /* copy format info */
 848        buf->btformat = buf->fmt->btformat;
 849        buf->btswap   = buf->fmt->btswap;
 850        return 0;
 851}
 852
 853/* ---------------------------------------------------------- */
 854
 855/* calculate geometry, build risc code */
 856int
 857bttv_overlay_risc(struct bttv *btv,
 858                  struct bttv_overlay *ov,
 859                  const struct bttv_format *fmt,
 860                  struct bttv_buffer *buf)
 861{
 862        /* check interleave, bottom+top fields */
 863        dprintk("%d: overlay fields: %s format: %s  size: %dx%d\n",
 864                btv->c.nr, v4l2_field_names[buf->vb.field],
 865                fmt->name, ov->w.width, ov->w.height);
 866
 867        /* calculate geometry */
 868        bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
 869                      V4L2_FIELD_HAS_BOTH(ov->field),
 870                      &bttv_tvnorms[ov->tvnorm],&buf->crop);
 871
 872        /* build risc code */
 873        switch (ov->field) {
 874        case V4L2_FIELD_TOP:
 875                bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 0);
 876                break;
 877        case V4L2_FIELD_BOTTOM:
 878                bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
 879                break;
 880        case V4L2_FIELD_INTERLACED:
 881                bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 1);
 882                bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
 883                break;
 884        default:
 885                BUG();
 886        }
 887
 888        /* copy format info */
 889        buf->btformat = fmt->btformat;
 890        buf->btswap   = fmt->btswap;
 891        buf->vb.field = ov->field;
 892        return 0;
 893}
 894