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 <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
  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        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
 583int
 584bttv_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
 635int
 636bttv_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 */
 695int
 696bttv_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 */
 855int
 856bttv_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