linux/drivers/media/pci/ivtv/ivtv-yuv.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3    yuv support
   4
   5    Copyright (C) 2007  Ian Armstrong <ian@iarmst.demon.co.uk>
   6
   7 */
   8
   9#include "ivtv-driver.h"
  10#include "ivtv-udma.h"
  11#include "ivtv-yuv.h"
  12
  13/* YUV buffer offsets */
  14const u32 yuv_offset[IVTV_YUV_BUFFERS] = {
  15        0x001a8600,
  16        0x00240400,
  17        0x002d8200,
  18        0x00370000,
  19        0x00029000,
  20        0x000C0E00,
  21        0x006B0400,
  22        0x00748200
  23};
  24
  25static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
  26                                  struct ivtv_dma_frame *args)
  27{
  28        struct ivtv_dma_page_info y_dma;
  29        struct ivtv_dma_page_info uv_dma;
  30        struct yuv_playback_info *yi = &itv->yuv_info;
  31        u8 frame = yi->draw_frame;
  32        struct yuv_frame_info *f = &yi->new_frame_info[frame];
  33        int y_pages, uv_pages;
  34        unsigned long y_buffer_offset, uv_buffer_offset;
  35        int y_decode_height, uv_decode_height, y_size;
  36
  37        y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame];
  38        uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET;
  39
  40        y_decode_height = uv_decode_height = f->src_h + f->src_y;
  41
  42        if (f->offset_y)
  43                y_buffer_offset += 720 * 16;
  44
  45        if (y_decode_height & 15)
  46                y_decode_height = (y_decode_height + 16) & ~15;
  47
  48        if (uv_decode_height & 31)
  49                uv_decode_height = (uv_decode_height + 32) & ~31;
  50
  51        y_size = 720 * y_decode_height;
  52
  53        /* Still in USE */
  54        if (dma->SG_length || dma->page_count) {
  55                IVTV_DEBUG_WARN
  56                    ("prep_user_dma: SG_length %d page_count %d still full?\n",
  57                     dma->SG_length, dma->page_count);
  58                return -EBUSY;
  59        }
  60
  61        ivtv_udma_get_page_info (&y_dma, (unsigned long)args->y_source, 720 * y_decode_height);
  62        ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height);
  63
  64        /* Pin user pages for DMA Xfer */
  65        y_pages = pin_user_pages_unlocked(y_dma.uaddr,
  66                        y_dma.page_count, &dma->map[0], FOLL_FORCE);
  67        uv_pages = 0; /* silence gcc. value is set and consumed only if: */
  68        if (y_pages == y_dma.page_count) {
  69                uv_pages = pin_user_pages_unlocked(uv_dma.uaddr,
  70                                uv_dma.page_count, &dma->map[y_pages],
  71                                FOLL_FORCE);
  72        }
  73
  74        if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
  75                int rc = -EFAULT;
  76
  77                if (y_pages == y_dma.page_count) {
  78                        IVTV_DEBUG_WARN
  79                                ("failed to map uv user pages, returned %d expecting %d\n",
  80                                 uv_pages, uv_dma.page_count);
  81
  82                        if (uv_pages >= 0) {
  83                                unpin_user_pages(&dma->map[y_pages], uv_pages);
  84                                rc = -EFAULT;
  85                        } else {
  86                                rc = uv_pages;
  87                        }
  88                } else {
  89                        IVTV_DEBUG_WARN
  90                                ("failed to map y user pages, returned %d expecting %d\n",
  91                                 y_pages, y_dma.page_count);
  92                }
  93                if (y_pages >= 0) {
  94                        unpin_user_pages(dma->map, y_pages);
  95                        /*
  96                         * Inherit the -EFAULT from rc's
  97                         * initialization, but allow it to be
  98                         * overridden by uv_pages above if it was an
  99                         * actual errno.
 100                         */
 101                } else {
 102                        rc = y_pages;
 103                }
 104                return rc;
 105        }
 106
 107        dma->page_count = y_pages + uv_pages;
 108
 109        /* Fill & map SG List */
 110        if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) {
 111                IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n");
 112                unpin_user_pages(dma->map, dma->page_count);
 113                dma->page_count = 0;
 114                return -ENOMEM;
 115        }
 116        dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
 117
 118        /* Fill SG Array with new values */
 119        ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size);
 120
 121        /* If we've offset the y plane, ensure top area is blanked */
 122        if (f->offset_y && yi->blanking_dmaptr) {
 123                dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16);
 124                dma->SGarray[dma->SG_length].src = cpu_to_le32(yi->blanking_dmaptr);
 125                dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]);
 126                dma->SG_length++;
 127        }
 128
 129        /* Tag SG Array with Interrupt Bit */
 130        dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000);
 131
 132        ivtv_udma_sync_for_device(itv);
 133        return 0;
 134}
 135
 136/* We rely on a table held in the firmware - Quick check. */
 137int ivtv_yuv_filter_check(struct ivtv *itv)
 138{
 139        int i, y, uv;
 140
 141        for (i = 0, y = 16, uv = 4; i < 16; i++, y += 24, uv += 12) {
 142                if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + y) != i << 16) ||
 143                    (read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + uv) != i << 16)) {
 144                        IVTV_WARN ("YUV filter table not found in firmware.\n");
 145                        return -1;
 146                }
 147        }
 148        return 0;
 149}
 150
 151static void ivtv_yuv_filter(struct ivtv *itv, int h_filter, int v_filter_1, int v_filter_2)
 152{
 153        u32 i, line;
 154
 155        /* If any filter is -1, then don't update it */
 156        if (h_filter > -1) {
 157                if (h_filter > 4)
 158                        h_filter = 4;
 159                i = IVTV_YUV_HORIZONTAL_FILTER_OFFSET + (h_filter * 384);
 160                for (line = 0; line < 16; line++) {
 161                        write_reg(read_dec(i), 0x02804);
 162                        write_reg(read_dec(i), 0x0281c);
 163                        i += 4;
 164                        write_reg(read_dec(i), 0x02808);
 165                        write_reg(read_dec(i), 0x02820);
 166                        i += 4;
 167                        write_reg(read_dec(i), 0x0280c);
 168                        write_reg(read_dec(i), 0x02824);
 169                        i += 4;
 170                        write_reg(read_dec(i), 0x02810);
 171                        write_reg(read_dec(i), 0x02828);
 172                        i += 4;
 173                        write_reg(read_dec(i), 0x02814);
 174                        write_reg(read_dec(i), 0x0282c);
 175                        i += 8;
 176                        write_reg(0, 0x02818);
 177                        write_reg(0, 0x02830);
 178                }
 179                IVTV_DEBUG_YUV("h_filter -> %d\n", h_filter);
 180        }
 181
 182        if (v_filter_1 > -1) {
 183                if (v_filter_1 > 4)
 184                        v_filter_1 = 4;
 185                i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_1 * 192);
 186                for (line = 0; line < 16; line++) {
 187                        write_reg(read_dec(i), 0x02900);
 188                        i += 4;
 189                        write_reg(read_dec(i), 0x02904);
 190                        i += 8;
 191                        write_reg(0, 0x02908);
 192                }
 193                IVTV_DEBUG_YUV("v_filter_1 -> %d\n", v_filter_1);
 194        }
 195
 196        if (v_filter_2 > -1) {
 197                if (v_filter_2 > 4)
 198                        v_filter_2 = 4;
 199                i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_2 * 192);
 200                for (line = 0; line < 16; line++) {
 201                        write_reg(read_dec(i), 0x0290c);
 202                        i += 4;
 203                        write_reg(read_dec(i), 0x02910);
 204                        i += 8;
 205                        write_reg(0, 0x02914);
 206                }
 207                IVTV_DEBUG_YUV("v_filter_2 -> %d\n", v_filter_2);
 208        }
 209}
 210
 211static void ivtv_yuv_handle_horizontal(struct ivtv *itv, struct yuv_frame_info *f)
 212{
 213        struct yuv_playback_info *yi = &itv->yuv_info;
 214        u32 reg_2834, reg_2838, reg_283c;
 215        u32 reg_2844, reg_2854, reg_285c;
 216        u32 reg_2864, reg_2874, reg_2890;
 217        u32 reg_2870, reg_2870_base, reg_2870_offset;
 218        int x_cutoff;
 219        int h_filter;
 220        u32 master_width;
 221
 222        IVTV_DEBUG_WARN
 223            ("Adjust to width %d src_w %d dst_w %d src_x %d dst_x %d\n",
 224             f->tru_w, f->src_w, f->dst_w, f->src_x, f->dst_x);
 225
 226        /* How wide is the src image */
 227        x_cutoff = f->src_w + f->src_x;
 228
 229        /* Set the display width */
 230        reg_2834 = f->dst_w;
 231        reg_2838 = reg_2834;
 232
 233        /* Set the display position */
 234        reg_2890 = f->dst_x;
 235
 236        /* Index into the image horizontally */
 237        reg_2870 = 0;
 238
 239        /* 2870 is normally fudged to align video coords with osd coords.
 240           If running full screen, it causes an unwanted left shift
 241           Remove the fudge if we almost fill the screen.
 242           Gradually adjust the offset to avoid the video 'snapping'
 243           left/right if it gets dragged through this region.
 244           Only do this if osd is full width. */
 245        if (f->vis_w == 720) {
 246                if ((f->tru_x - f->pan_x > -1) && (f->tru_x - f->pan_x <= 40) && (f->dst_w >= 680))
 247                        reg_2870 = 10 - (f->tru_x - f->pan_x) / 4;
 248                else if ((f->tru_x - f->pan_x < 0) && (f->tru_x - f->pan_x >= -20) && (f->dst_w >= 660))
 249                        reg_2870 = (10 + (f->tru_x - f->pan_x) / 2);
 250
 251                if (f->dst_w >= f->src_w)
 252                        reg_2870 = reg_2870 << 16 | reg_2870;
 253                else
 254                        reg_2870 = ((reg_2870 & ~1) << 15) | (reg_2870 & ~1);
 255        }
 256
 257        if (f->dst_w < f->src_w)
 258                reg_2870 = 0x000d000e - reg_2870;
 259        else
 260                reg_2870 = 0x0012000e - reg_2870;
 261
 262        /* We're also using 2870 to shift the image left (src_x & negative dst_x) */
 263        reg_2870_offset = (f->src_x * ((f->dst_w << 21) / f->src_w)) >> 19;
 264
 265        if (f->dst_w >= f->src_w) {
 266                x_cutoff &= ~1;
 267                master_width = (f->src_w * 0x00200000) / (f->dst_w);
 268                if (master_width * f->dst_w != f->src_w * 0x00200000)
 269                        master_width++;
 270                reg_2834 = (reg_2834 << 16) | x_cutoff;
 271                reg_2838 = (reg_2838 << 16) | x_cutoff;
 272                reg_283c = master_width >> 2;
 273                reg_2844 = master_width >> 2;
 274                reg_2854 = master_width;
 275                reg_285c = master_width >> 1;
 276                reg_2864 = master_width >> 1;
 277
 278                /* We also need to factor in the scaling
 279                   (src_w - dst_w) / (src_w / 4) */
 280                if (f->dst_w > f->src_w)
 281                        reg_2870_base = ((f->dst_w - f->src_w)<<16) / (f->src_w <<14);
 282                else
 283                        reg_2870_base = 0;
 284
 285                reg_2870 += (((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 2) + (reg_2870_base << 17 | reg_2870_base);
 286                reg_2874 = 0;
 287        } else if (f->dst_w < f->src_w / 2) {
 288                master_width = (f->src_w * 0x00080000) / f->dst_w;
 289                if (master_width * f->dst_w != f->src_w * 0x00080000)
 290                        master_width++;
 291                reg_2834 = (reg_2834 << 16) | x_cutoff;
 292                reg_2838 = (reg_2838 << 16) | x_cutoff;
 293                reg_283c = master_width >> 2;
 294                reg_2844 = master_width >> 1;
 295                reg_2854 = master_width;
 296                reg_285c = master_width >> 1;
 297                reg_2864 = master_width >> 1;
 298                reg_2870 += ((reg_2870_offset << 15) & 0xFFFF0000) | reg_2870_offset;
 299                reg_2870 += (5 - (((f->src_w + f->src_w / 2) - 1) / f->dst_w)) << 16;
 300                reg_2874 = 0x00000012;
 301        } else {
 302                master_width = (f->src_w * 0x00100000) / f->dst_w;
 303                if (master_width * f->dst_w != f->src_w * 0x00100000)
 304                        master_width++;
 305                reg_2834 = (reg_2834 << 16) | x_cutoff;
 306                reg_2838 = (reg_2838 << 16) | x_cutoff;
 307                reg_283c = master_width >> 2;
 308                reg_2844 = master_width >> 1;
 309                reg_2854 = master_width;
 310                reg_285c = master_width >> 1;
 311                reg_2864 = master_width >> 1;
 312                reg_2870 += ((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 1;
 313                reg_2870 += (5 - (((f->src_w * 3) - 1) / f->dst_w)) << 16;
 314                reg_2874 = 0x00000001;
 315        }
 316
 317        /* Select the horizontal filter */
 318        if (f->src_w == f->dst_w) {
 319                /* An exact size match uses filter 0 */
 320                h_filter = 0;
 321        } else {
 322                /* Figure out which filter to use */
 323                h_filter = ((f->src_w << 16) / f->dst_w) >> 15;
 324                h_filter = (h_filter >> 1) + (h_filter & 1);
 325                /* Only an exact size match can use filter 0 */
 326                h_filter += !h_filter;
 327        }
 328
 329        write_reg(reg_2834, 0x02834);
 330        write_reg(reg_2838, 0x02838);
 331        IVTV_DEBUG_YUV("Update reg 0x2834 %08x->%08x 0x2838 %08x->%08x\n",
 332                       yi->reg_2834, reg_2834, yi->reg_2838, reg_2838);
 333
 334        write_reg(reg_283c, 0x0283c);
 335        write_reg(reg_2844, 0x02844);
 336
 337        IVTV_DEBUG_YUV("Update reg 0x283c %08x->%08x 0x2844 %08x->%08x\n",
 338                       yi->reg_283c, reg_283c, yi->reg_2844, reg_2844);
 339
 340        write_reg(0x00080514, 0x02840);
 341        write_reg(0x00100514, 0x02848);
 342        IVTV_DEBUG_YUV("Update reg 0x2840 %08x->%08x 0x2848 %08x->%08x\n",
 343                       yi->reg_2840, 0x00080514, yi->reg_2848, 0x00100514);
 344
 345        write_reg(reg_2854, 0x02854);
 346        IVTV_DEBUG_YUV("Update reg 0x2854 %08x->%08x \n",
 347                       yi->reg_2854, reg_2854);
 348
 349        write_reg(reg_285c, 0x0285c);
 350        write_reg(reg_2864, 0x02864);
 351        IVTV_DEBUG_YUV("Update reg 0x285c %08x->%08x 0x2864 %08x->%08x\n",
 352                       yi->reg_285c, reg_285c, yi->reg_2864, reg_2864);
 353
 354        write_reg(reg_2874, 0x02874);
 355        IVTV_DEBUG_YUV("Update reg 0x2874 %08x->%08x\n",
 356                       yi->reg_2874, reg_2874);
 357
 358        write_reg(reg_2870, 0x02870);
 359        IVTV_DEBUG_YUV("Update reg 0x2870 %08x->%08x\n",
 360                       yi->reg_2870, reg_2870);
 361
 362        write_reg(reg_2890, 0x02890);
 363        IVTV_DEBUG_YUV("Update reg 0x2890 %08x->%08x\n",
 364                       yi->reg_2890, reg_2890);
 365
 366        /* Only update the filter if we really need to */
 367        if (h_filter != yi->h_filter) {
 368                ivtv_yuv_filter(itv, h_filter, -1, -1);
 369                yi->h_filter = h_filter;
 370        }
 371}
 372
 373static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *f)
 374{
 375        struct yuv_playback_info *yi = &itv->yuv_info;
 376        u32 master_height;
 377        u32 reg_2918, reg_291c, reg_2920, reg_2928;
 378        u32 reg_2930, reg_2934, reg_293c;
 379        u32 reg_2940, reg_2944, reg_294c;
 380        u32 reg_2950, reg_2954, reg_2958, reg_295c;
 381        u32 reg_2960, reg_2964, reg_2968, reg_296c;
 382        u32 reg_289c;
 383        u32 src_major_y, src_minor_y;
 384        u32 src_major_uv, src_minor_uv;
 385        u32 reg_2964_base, reg_2968_base;
 386        int v_filter_1, v_filter_2;
 387
 388        IVTV_DEBUG_WARN
 389            ("Adjust to height %d src_h %d dst_h %d src_y %d dst_y %d\n",
 390             f->tru_h, f->src_h, f->dst_h, f->src_y, f->dst_y);
 391
 392        /* What scaling mode is being used... */
 393        IVTV_DEBUG_YUV("Scaling mode Y: %s\n",
 394                       f->interlaced_y ? "Interlaced" : "Progressive");
 395
 396        IVTV_DEBUG_YUV("Scaling mode UV: %s\n",
 397                       f->interlaced_uv ? "Interlaced" : "Progressive");
 398
 399        /* What is the source video being treated as... */
 400        IVTV_DEBUG_WARN("Source video: %s\n",
 401                        f->interlaced ? "Interlaced" : "Progressive");
 402
 403        /* We offset into the image using two different index methods, so split
 404           the y source coord into two parts. */
 405        if (f->src_y < 8) {
 406                src_minor_uv = f->src_y;
 407                src_major_uv = 0;
 408        } else {
 409                src_minor_uv = 8;
 410                src_major_uv = f->src_y - 8;
 411        }
 412
 413        src_minor_y = src_minor_uv;
 414        src_major_y = src_major_uv;
 415
 416        if (f->offset_y)
 417                src_minor_y += 16;
 418
 419        if (f->interlaced_y)
 420                reg_2918 = (f->dst_h << 16) | (f->src_h + src_minor_y);
 421        else
 422                reg_2918 = (f->dst_h << 16) | ((f->src_h + src_minor_y) << 1);
 423
 424        if (f->interlaced_uv)
 425                reg_291c = (f->dst_h << 16) | ((f->src_h + src_minor_uv) >> 1);
 426        else
 427                reg_291c = (f->dst_h << 16) | (f->src_h + src_minor_uv);
 428
 429        reg_2964_base = (src_minor_y * ((f->dst_h << 16) / f->src_h)) >> 14;
 430        reg_2968_base = (src_minor_uv * ((f->dst_h << 16) / f->src_h)) >> 14;
 431
 432        if (f->dst_h / 2 >= f->src_h && !f->interlaced_y) {
 433                master_height = (f->src_h * 0x00400000) / f->dst_h;
 434                if ((f->src_h * 0x00400000) - (master_height * f->dst_h) >= f->dst_h / 2)
 435                        master_height++;
 436                reg_2920 = master_height >> 2;
 437                reg_2928 = master_height >> 3;
 438                reg_2930 = master_height;
 439                reg_2940 = master_height >> 1;
 440                reg_2964_base >>= 3;
 441                reg_2968_base >>= 3;
 442                reg_296c = 0x00000000;
 443        } else if (f->dst_h >= f->src_h) {
 444                master_height = (f->src_h * 0x00400000) / f->dst_h;
 445                master_height = (master_height >> 1) + (master_height & 1);
 446                reg_2920 = master_height >> 2;
 447                reg_2928 = master_height >> 2;
 448                reg_2930 = master_height;
 449                reg_2940 = master_height >> 1;
 450                reg_296c = 0x00000000;
 451                if (f->interlaced_y) {
 452                        reg_2964_base >>= 3;
 453                } else {
 454                        reg_296c++;
 455                        reg_2964_base >>= 2;
 456                }
 457                if (f->interlaced_uv)
 458                        reg_2928 >>= 1;
 459                reg_2968_base >>= 3;
 460        } else if (f->dst_h >= f->src_h / 2) {
 461                master_height = (f->src_h * 0x00200000) / f->dst_h;
 462                master_height = (master_height >> 1) + (master_height & 1);
 463                reg_2920 = master_height >> 2;
 464                reg_2928 = master_height >> 2;
 465                reg_2930 = master_height;
 466                reg_2940 = master_height;
 467                reg_296c = 0x00000101;
 468                if (f->interlaced_y) {
 469                        reg_2964_base >>= 2;
 470                } else {
 471                        reg_296c++;
 472                        reg_2964_base >>= 1;
 473                }
 474                if (f->interlaced_uv)
 475                        reg_2928 >>= 1;
 476                reg_2968_base >>= 2;
 477        } else {
 478                master_height = (f->src_h * 0x00100000) / f->dst_h;
 479                master_height = (master_height >> 1) + (master_height & 1);
 480                reg_2920 = master_height >> 2;
 481                reg_2928 = master_height >> 2;
 482                reg_2930 = master_height;
 483                reg_2940 = master_height;
 484                reg_2964_base >>= 1;
 485                reg_2968_base >>= 2;
 486                reg_296c = 0x00000102;
 487        }
 488
 489        /* FIXME These registers change depending on scaled / unscaled output
 490           We really need to work out what they should be */
 491        if (f->src_h == f->dst_h) {
 492                reg_2934 = 0x00020000;
 493                reg_293c = 0x00100000;
 494                reg_2944 = 0x00040000;
 495                reg_294c = 0x000b0000;
 496        } else {
 497                reg_2934 = 0x00000FF0;
 498                reg_293c = 0x00000FF0;
 499                reg_2944 = 0x00000FF0;
 500                reg_294c = 0x00000FF0;
 501        }
 502
 503        /* The first line to be displayed */
 504        reg_2950 = 0x00010000 + src_major_y;
 505        if (f->interlaced_y)
 506                reg_2950 += 0x00010000;
 507        reg_2954 = reg_2950 + 1;
 508
 509        reg_2958 = 0x00010000 + (src_major_y >> 1);
 510        if (f->interlaced_uv)
 511                reg_2958 += 0x00010000;
 512        reg_295c = reg_2958 + 1;
 513
 514        if (yi->decode_height == 480)
 515                reg_289c = 0x011e0017;
 516        else
 517                reg_289c = 0x01500017;
 518
 519        if (f->dst_y < 0)
 520                reg_289c = (reg_289c - ((f->dst_y & ~1)<<15))-(f->dst_y >>1);
 521        else
 522                reg_289c = (reg_289c + ((f->dst_y & ~1)<<15))+(f->dst_y >>1);
 523
 524        /* How much of the source to decode.
 525           Take into account the source offset */
 526        reg_2960 = ((src_minor_y + f->src_h + src_major_y) - 1) |
 527                (((src_minor_uv + f->src_h + src_major_uv - 1) & ~1) << 15);
 528
 529        /* Calculate correct value for register 2964 */
 530        if (f->src_h == f->dst_h) {
 531                reg_2964 = 1;
 532        } else {
 533                reg_2964 = 2 + ((f->dst_h << 1) / f->src_h);
 534                reg_2964 = (reg_2964 >> 1) + (reg_2964 & 1);
 535        }
 536        reg_2968 = (reg_2964 << 16) + reg_2964 + (reg_2964 >> 1);
 537        reg_2964 = (reg_2964 << 16) + reg_2964 + (reg_2964 * 46 / 94);
 538
 539        /* Okay, we've wasted time working out the correct value,
 540           but if we use it, it fouls the the window alignment.
 541           Fudge it to what we want... */
 542        reg_2964 = 0x00010001 + ((reg_2964 & 0x0000FFFF) - (reg_2964 >> 16));
 543        reg_2968 = 0x00010001 + ((reg_2968 & 0x0000FFFF) - (reg_2968 >> 16));
 544
 545        /* Deviate further from what it should be. I find the flicker headache
 546           inducing so try to reduce it slightly. Leave 2968 as-is otherwise
 547           colours foul. */
 548        if ((reg_2964 != 0x00010001) && (f->dst_h / 2 <= f->src_h))
 549                reg_2964 = (reg_2964 & 0xFFFF0000) + ((reg_2964 & 0x0000FFFF) / 2);
 550
 551        if (!f->interlaced_y)
 552                reg_2964 -= 0x00010001;
 553        if (!f->interlaced_uv)
 554                reg_2968 -= 0x00010001;
 555
 556        reg_2964 += ((reg_2964_base << 16) | reg_2964_base);
 557        reg_2968 += ((reg_2968_base << 16) | reg_2968_base);
 558
 559        /* Select the vertical filter */
 560        if (f->src_h == f->dst_h) {
 561                /* An exact size match uses filter 0/1 */
 562                v_filter_1 = 0;
 563                v_filter_2 = 1;
 564        } else {
 565                /* Figure out which filter to use */
 566                v_filter_1 = ((f->src_h << 16) / f->dst_h) >> 15;
 567                v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
 568                /* Only an exact size match can use filter 0 */
 569                v_filter_1 += !v_filter_1;
 570                v_filter_2 = v_filter_1;
 571        }
 572
 573        write_reg(reg_2934, 0x02934);
 574        write_reg(reg_293c, 0x0293c);
 575        IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n",
 576                       yi->reg_2934, reg_2934, yi->reg_293c, reg_293c);
 577        write_reg(reg_2944, 0x02944);
 578        write_reg(reg_294c, 0x0294c);
 579        IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n",
 580                       yi->reg_2944, reg_2944, yi->reg_294c, reg_294c);
 581
 582        /* Ensure 2970 is 0 (does it ever change ?) */
 583/*      write_reg(0,0x02970); */
 584/*      IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n", yi->reg_2970, 0); */
 585
 586        write_reg(reg_2930, 0x02938);
 587        write_reg(reg_2930, 0x02930);
 588        IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n",
 589                       yi->reg_2930, reg_2930, yi->reg_2938, reg_2930);
 590
 591        write_reg(reg_2928, 0x02928);
 592        write_reg(reg_2928 + 0x514, 0x0292C);
 593        IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n",
 594                       yi->reg_2928, reg_2928, yi->reg_292c, reg_2928 + 0x514);
 595
 596        write_reg(reg_2920, 0x02920);
 597        write_reg(reg_2920 + 0x514, 0x02924);
 598        IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n",
 599                       yi->reg_2920, reg_2920, yi->reg_2924, reg_2920 + 0x514);
 600
 601        write_reg(reg_2918, 0x02918);
 602        write_reg(reg_291c, 0x0291C);
 603        IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n",
 604                       yi->reg_2918, reg_2918, yi->reg_291c, reg_291c);
 605
 606        write_reg(reg_296c, 0x0296c);
 607        IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n",
 608                       yi->reg_296c, reg_296c);
 609
 610        write_reg(reg_2940, 0x02948);
 611        write_reg(reg_2940, 0x02940);
 612        IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n",
 613                       yi->reg_2940, reg_2940, yi->reg_2948, reg_2940);
 614
 615        write_reg(reg_2950, 0x02950);
 616        write_reg(reg_2954, 0x02954);
 617        IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n",
 618                       yi->reg_2950, reg_2950, yi->reg_2954, reg_2954);
 619
 620        write_reg(reg_2958, 0x02958);
 621        write_reg(reg_295c, 0x0295C);
 622        IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n",
 623                       yi->reg_2958, reg_2958, yi->reg_295c, reg_295c);
 624
 625        write_reg(reg_2960, 0x02960);
 626        IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n",
 627                       yi->reg_2960, reg_2960);
 628
 629        write_reg(reg_2964, 0x02964);
 630        write_reg(reg_2968, 0x02968);
 631        IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n",
 632                       yi->reg_2964, reg_2964, yi->reg_2968, reg_2968);
 633
 634        write_reg(reg_289c, 0x0289c);
 635        IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n",
 636                       yi->reg_289c, reg_289c);
 637
 638        /* Only update filter 1 if we really need to */
 639        if (v_filter_1 != yi->v_filter_1) {
 640                ivtv_yuv_filter(itv, -1, v_filter_1, -1);
 641                yi->v_filter_1 = v_filter_1;
 642        }
 643
 644        /* Only update filter 2 if we really need to */
 645        if (v_filter_2 != yi->v_filter_2) {
 646                ivtv_yuv_filter(itv, -1, -1, v_filter_2);
 647                yi->v_filter_2 = v_filter_2;
 648        }
 649}
 650
 651/* Modify the supplied coordinate information to fit the visible osd area */
 652static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f)
 653{
 654        struct yuv_frame_info *of = &itv->yuv_info.old_frame_info;
 655        int osd_crop;
 656        u32 osd_scale;
 657        u32 yuv_update = 0;
 658
 659        /* Sorry, but no negative coords for src */
 660        if (f->src_x < 0)
 661                f->src_x = 0;
 662        if (f->src_y < 0)
 663                f->src_y = 0;
 664
 665        /* Can only reduce width down to 1/4 original size */
 666        if ((osd_crop = f->src_w - 4 * f->dst_w) > 0) {
 667                f->src_x += osd_crop / 2;
 668                f->src_w = (f->src_w - osd_crop) & ~3;
 669                f->dst_w = f->src_w / 4;
 670                f->dst_w += f->dst_w & 1;
 671        }
 672
 673        /* Can only reduce height down to 1/4 original size */
 674        if (f->src_h / f->dst_h >= 2) {
 675                /* Overflow may be because we're running progressive,
 676                   so force mode switch */
 677                f->interlaced_y = 1;
 678                /* Make sure we're still within limits for interlace */
 679                if ((osd_crop = f->src_h - 4 * f->dst_h) > 0) {
 680                        /* If we reach here we'll have to force the height. */
 681                        f->src_y += osd_crop / 2;
 682                        f->src_h = (f->src_h - osd_crop) & ~3;
 683                        f->dst_h = f->src_h / 4;
 684                        f->dst_h += f->dst_h & 1;
 685                }
 686        }
 687
 688        /* If there's nothing to safe to display, we may as well stop now */
 689        if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
 690            (int)f->src_w <= 2 || (int)f->src_h <= 2) {
 691                return IVTV_YUV_UPDATE_INVALID;
 692        }
 693
 694        /* Ensure video remains inside OSD area */
 695        osd_scale = (f->src_h << 16) / f->dst_h;
 696
 697        if ((osd_crop = f->pan_y - f->dst_y) > 0) {
 698                /* Falls off the upper edge - crop */
 699                f->src_y += (osd_scale * osd_crop) >> 16;
 700                f->src_h -= (osd_scale * osd_crop) >> 16;
 701                f->dst_h -= osd_crop;
 702                f->dst_y = 0;
 703        } else {
 704                f->dst_y -= f->pan_y;
 705        }
 706
 707        if ((osd_crop = f->dst_h + f->dst_y - f->vis_h) > 0) {
 708                /* Falls off the lower edge - crop */
 709                f->dst_h -= osd_crop;
 710                f->src_h -= (osd_scale * osd_crop) >> 16;
 711        }
 712
 713        osd_scale = (f->src_w << 16) / f->dst_w;
 714
 715        if ((osd_crop = f->pan_x - f->dst_x) > 0) {
 716                /* Fall off the left edge - crop */
 717                f->src_x += (osd_scale * osd_crop) >> 16;
 718                f->src_w -= (osd_scale * osd_crop) >> 16;
 719                f->dst_w -= osd_crop;
 720                f->dst_x = 0;
 721        } else {
 722                f->dst_x -= f->pan_x;
 723        }
 724
 725        if ((osd_crop = f->dst_w + f->dst_x - f->vis_w) > 0) {
 726                /* Falls off the right edge - crop */
 727                f->dst_w -= osd_crop;
 728                f->src_w -= (osd_scale * osd_crop) >> 16;
 729        }
 730
 731        if (itv->yuv_info.track_osd) {
 732                /* The OSD can be moved. Track to it */
 733                f->dst_x += itv->yuv_info.osd_x_offset;
 734                f->dst_y += itv->yuv_info.osd_y_offset;
 735        }
 736
 737        /* Width & height for both src & dst must be even.
 738           Same for coordinates. */
 739        f->dst_w &= ~1;
 740        f->dst_x &= ~1;
 741
 742        f->src_w += f->src_x & 1;
 743        f->src_x &= ~1;
 744
 745        f->src_w &= ~1;
 746        f->dst_w &= ~1;
 747
 748        f->dst_h &= ~1;
 749        f->dst_y &= ~1;
 750
 751        f->src_h += f->src_y & 1;
 752        f->src_y &= ~1;
 753
 754        f->src_h &= ~1;
 755        f->dst_h &= ~1;
 756
 757        /* Due to rounding, we may have reduced the output size to <1/4 of
 758           the source. Check again, but this time just resize. Don't change
 759           source coordinates */
 760        if (f->dst_w < f->src_w / 4) {
 761                f->src_w &= ~3;
 762                f->dst_w = f->src_w / 4;
 763                f->dst_w += f->dst_w & 1;
 764        }
 765        if (f->dst_h < f->src_h / 4) {
 766                f->src_h &= ~3;
 767                f->dst_h = f->src_h / 4;
 768                f->dst_h += f->dst_h & 1;
 769        }
 770
 771        /* Check again. If there's nothing to safe to display, stop now */
 772        if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
 773            (int)f->src_w <= 2 || (int)f->src_h <= 2) {
 774                return IVTV_YUV_UPDATE_INVALID;
 775        }
 776
 777        /* Both x offset & width are linked, so they have to be done together */
 778        if ((of->dst_w != f->dst_w) || (of->src_w != f->src_w) ||
 779            (of->dst_x != f->dst_x) || (of->src_x != f->src_x) ||
 780            (of->pan_x != f->pan_x) || (of->vis_w != f->vis_w)) {
 781                yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL;
 782        }
 783
 784        if ((of->src_h != f->src_h) || (of->dst_h != f->dst_h) ||
 785            (of->dst_y != f->dst_y) || (of->src_y != f->src_y) ||
 786            (of->pan_y != f->pan_y) || (of->vis_h != f->vis_h) ||
 787            (of->lace_mode != f->lace_mode) ||
 788            (of->interlaced_y != f->interlaced_y) ||
 789            (of->interlaced_uv != f->interlaced_uv)) {
 790                yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
 791        }
 792
 793        return yuv_update;
 794}
 795
 796/* Update the scaling register to the requested value */
 797void ivtv_yuv_work_handler(struct ivtv *itv)
 798{
 799        struct yuv_playback_info *yi = &itv->yuv_info;
 800        struct yuv_frame_info f;
 801        int frame = yi->update_frame;
 802        u32 yuv_update;
 803
 804        IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);
 805        f = yi->new_frame_info[frame];
 806
 807        if (yi->track_osd) {
 808                /* Snapshot the osd pan info */
 809                f.pan_x = yi->osd_x_pan;
 810                f.pan_y = yi->osd_y_pan;
 811                f.vis_w = yi->osd_vis_w;
 812                f.vis_h = yi->osd_vis_h;
 813        } else {
 814                /* Not tracking the osd, so assume full screen */
 815                f.pan_x = 0;
 816                f.pan_y = 0;
 817                f.vis_w = 720;
 818                f.vis_h = yi->decode_height;
 819        }
 820
 821        /* Calculate the display window coordinates. Exit if nothing left */
 822        if (!(yuv_update = ivtv_yuv_window_setup(itv, &f)))
 823                return;
 824
 825        if (yuv_update & IVTV_YUV_UPDATE_INVALID) {
 826                write_reg(0x01008080, 0x2898);
 827        } else if (yuv_update) {
 828                write_reg(0x00108080, 0x2898);
 829
 830                if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)
 831                        ivtv_yuv_handle_horizontal(itv, &f);
 832
 833                if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)
 834                        ivtv_yuv_handle_vertical(itv, &f);
 835        }
 836        yi->old_frame_info = f;
 837}
 838
 839static void ivtv_yuv_init(struct ivtv *itv)
 840{
 841        struct yuv_playback_info *yi = &itv->yuv_info;
 842
 843        IVTV_DEBUG_YUV("ivtv_yuv_init\n");
 844
 845        /* Take a snapshot of the current register settings */
 846        yi->reg_2834 = read_reg(0x02834);
 847        yi->reg_2838 = read_reg(0x02838);
 848        yi->reg_283c = read_reg(0x0283c);
 849        yi->reg_2840 = read_reg(0x02840);
 850        yi->reg_2844 = read_reg(0x02844);
 851        yi->reg_2848 = read_reg(0x02848);
 852        yi->reg_2854 = read_reg(0x02854);
 853        yi->reg_285c = read_reg(0x0285c);
 854        yi->reg_2864 = read_reg(0x02864);
 855        yi->reg_2870 = read_reg(0x02870);
 856        yi->reg_2874 = read_reg(0x02874);
 857        yi->reg_2898 = read_reg(0x02898);
 858        yi->reg_2890 = read_reg(0x02890);
 859
 860        yi->reg_289c = read_reg(0x0289c);
 861        yi->reg_2918 = read_reg(0x02918);
 862        yi->reg_291c = read_reg(0x0291c);
 863        yi->reg_2920 = read_reg(0x02920);
 864        yi->reg_2924 = read_reg(0x02924);
 865        yi->reg_2928 = read_reg(0x02928);
 866        yi->reg_292c = read_reg(0x0292c);
 867        yi->reg_2930 = read_reg(0x02930);
 868        yi->reg_2934 = read_reg(0x02934);
 869        yi->reg_2938 = read_reg(0x02938);
 870        yi->reg_293c = read_reg(0x0293c);
 871        yi->reg_2940 = read_reg(0x02940);
 872        yi->reg_2944 = read_reg(0x02944);
 873        yi->reg_2948 = read_reg(0x02948);
 874        yi->reg_294c = read_reg(0x0294c);
 875        yi->reg_2950 = read_reg(0x02950);
 876        yi->reg_2954 = read_reg(0x02954);
 877        yi->reg_2958 = read_reg(0x02958);
 878        yi->reg_295c = read_reg(0x0295c);
 879        yi->reg_2960 = read_reg(0x02960);
 880        yi->reg_2964 = read_reg(0x02964);
 881        yi->reg_2968 = read_reg(0x02968);
 882        yi->reg_296c = read_reg(0x0296c);
 883        yi->reg_2970 = read_reg(0x02970);
 884
 885        yi->v_filter_1 = -1;
 886        yi->v_filter_2 = -1;
 887        yi->h_filter = -1;
 888
 889        /* Set some valid size info */
 890        yi->osd_x_offset = read_reg(0x02a04) & 0x00000FFF;
 891        yi->osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF;
 892
 893        /* Bit 2 of reg 2878 indicates current decoder output format
 894           0 : NTSC    1 : PAL */
 895        if (read_reg(0x2878) & 4)
 896                yi->decode_height = 576;
 897        else
 898                yi->decode_height = 480;
 899
 900        if (!itv->osd_info) {
 901                yi->osd_vis_w = 720 - yi->osd_x_offset;
 902                yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
 903        } else {
 904                /* If no visible size set, assume full size */
 905                if (!yi->osd_vis_w)
 906                        yi->osd_vis_w = 720 - yi->osd_x_offset;
 907
 908                if (!yi->osd_vis_h) {
 909                        yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
 910                } else if (yi->osd_vis_h + yi->osd_y_offset > yi->decode_height) {
 911                        /* If output video standard has changed, requested height may
 912                           not be legal */
 913                        IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
 914                                        yi->osd_vis_h + yi->osd_y_offset,
 915                                        yi->decode_height);
 916                        yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
 917                }
 918        }
 919
 920        /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
 921        yi->blanking_ptr = kzalloc(720 * 16, GFP_ATOMIC|__GFP_NOWARN);
 922        if (yi->blanking_ptr) {
 923                yi->blanking_dmaptr = pci_map_single(itv->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
 924        } else {
 925                yi->blanking_dmaptr = 0;
 926                IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
 927        }
 928
 929        /* Enable YUV decoder output */
 930        write_reg_sync(0x01, IVTV_REG_VDM);
 931
 932        set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
 933        atomic_set(&yi->next_dma_frame, 0);
 934}
 935
 936/* Get next available yuv buffer on PVR350 */
 937static void ivtv_yuv_next_free(struct ivtv *itv)
 938{
 939        int draw, display;
 940        struct yuv_playback_info *yi = &itv->yuv_info;
 941
 942        if (atomic_read(&yi->next_dma_frame) == -1)
 943                ivtv_yuv_init(itv);
 944
 945        draw = atomic_read(&yi->next_fill_frame);
 946        display = atomic_read(&yi->next_dma_frame);
 947
 948        if (display > draw)
 949                display -= IVTV_YUV_BUFFERS;
 950
 951        if (draw - display >= yi->max_frames_buffered)
 952                draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS;
 953        else
 954                yi->new_frame_info[draw].update = 0;
 955
 956        yi->draw_frame = draw;
 957}
 958
 959/* Set up frame according to ivtv_dma_frame parameters */
 960static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
 961{
 962        struct yuv_playback_info *yi = &itv->yuv_info;
 963        u8 frame = yi->draw_frame;
 964        u8 last_frame = (u8)(frame - 1) % IVTV_YUV_BUFFERS;
 965        struct yuv_frame_info *nf = &yi->new_frame_info[frame];
 966        struct yuv_frame_info *of = &yi->new_frame_info[last_frame];
 967        int lace_threshold = yi->lace_threshold;
 968
 969        /* Preserve old update flag in case we're overwriting a queued frame */
 970        int update = nf->update;
 971
 972        /* Take a snapshot of the yuv coordinate information */
 973        nf->src_x = args->src.left;
 974        nf->src_y = args->src.top;
 975        nf->src_w = args->src.width;
 976        nf->src_h = args->src.height;
 977        nf->dst_x = args->dst.left;
 978        nf->dst_y = args->dst.top;
 979        nf->dst_w = args->dst.width;
 980        nf->dst_h = args->dst.height;
 981        nf->tru_x = args->dst.left;
 982        nf->tru_w = args->src_width;
 983        nf->tru_h = args->src_height;
 984
 985        /* Are we going to offset the Y plane */
 986        nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
 987
 988        nf->update = 0;
 989        nf->interlaced_y = 0;
 990        nf->interlaced_uv = 0;
 991        nf->delay = 0;
 992        nf->sync_field = 0;
 993        nf->lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK;
 994
 995        if (lace_threshold < 0)
 996                lace_threshold = yi->decode_height - 1;
 997
 998        /* Work out the lace settings */
 999        switch (nf->lace_mode) {
1000        case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */
1001                nf->interlaced = 0;
1002                if (nf->tru_h < 512 || (nf->tru_h > 576 && nf->tru_h < 1021))
1003                        nf->interlaced_y = 0;
1004                else
1005                        nf->interlaced_y = 1;
1006
1007                if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
1008                        nf->interlaced_uv = 0;
1009                else
1010                        nf->interlaced_uv = 1;
1011                break;
1012
1013        case IVTV_YUV_MODE_AUTO:
1014                if (nf->tru_h <= lace_threshold || nf->tru_h > 576 || nf->tru_w > 720) {
1015                        nf->interlaced = 0;
1016                        if ((nf->tru_h < 512) ||
1017                            (nf->tru_h > 576 && nf->tru_h < 1021) ||
1018                            (nf->tru_w > 720 && nf->tru_h < 1021))
1019                                nf->interlaced_y = 0;
1020                        else
1021                                nf->interlaced_y = 1;
1022                        if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
1023                                nf->interlaced_uv = 0;
1024                        else
1025                                nf->interlaced_uv = 1;
1026                } else {
1027                        nf->interlaced = 1;
1028                        nf->interlaced_y = 1;
1029                        nf->interlaced_uv = 1;
1030                }
1031                break;
1032
1033        case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
1034        default:
1035                nf->interlaced = 1;
1036                nf->interlaced_y = 1;
1037                nf->interlaced_uv = 1;
1038                break;
1039        }
1040
1041        if (memcmp(&yi->old_frame_info_args, nf, sizeof(*nf))) {
1042                yi->old_frame_info_args = *nf;
1043                nf->update = 1;
1044                IVTV_DEBUG_YUV("Requesting reg update for frame %d\n", frame);
1045        }
1046
1047        nf->update |= update;
1048        nf->sync_field = yi->lace_sync_field;
1049        nf->delay = nf->sync_field != of->sync_field;
1050}
1051
1052/* Frame is complete & ready for display */
1053void ivtv_yuv_frame_complete(struct ivtv *itv)
1054{
1055        atomic_set(&itv->yuv_info.next_fill_frame,
1056                        (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
1057}
1058
1059static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1060{
1061        DEFINE_WAIT(wait);
1062        int rc = 0;
1063        int got_sig = 0;
1064        /* DMA the frame */
1065        mutex_lock(&itv->udma.lock);
1066
1067        if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) {
1068                mutex_unlock(&itv->udma.lock);
1069                return rc;
1070        }
1071
1072        ivtv_udma_prepare(itv);
1073        prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
1074        /* if no UDMA is pending and no UDMA is in progress, then the DMA
1075           is finished */
1076        while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
1077               test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
1078                /* don't interrupt if the DMA is in progress but break off
1079                   a still pending DMA. */
1080                got_sig = signal_pending(current);
1081                if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
1082                        break;
1083                got_sig = 0;
1084                schedule();
1085        }
1086        finish_wait(&itv->dma_waitq, &wait);
1087
1088        /* Unmap Last DMA Xfer */
1089        ivtv_udma_unmap(itv);
1090
1091        if (got_sig) {
1092                IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
1093                mutex_unlock(&itv->udma.lock);
1094                return -EINTR;
1095        }
1096
1097        ivtv_yuv_frame_complete(itv);
1098
1099        mutex_unlock(&itv->udma.lock);
1100        return rc;
1101}
1102
1103/* Setup frame according to V4L2 parameters */
1104void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
1105{
1106        struct yuv_playback_info *yi = &itv->yuv_info;
1107        struct ivtv_dma_frame dma_args;
1108
1109        ivtv_yuv_next_free(itv);
1110
1111        /* Copy V4L2 parameters to an ivtv_dma_frame struct... */
1112        dma_args.y_source = NULL;
1113        dma_args.uv_source = NULL;
1114        dma_args.src.left = 0;
1115        dma_args.src.top = 0;
1116        dma_args.src.width = yi->v4l2_src_w;
1117        dma_args.src.height = yi->v4l2_src_h;
1118        dma_args.dst = yi->main_rect;
1119        dma_args.src_width = yi->v4l2_src_w;
1120        dma_args.src_height = yi->v4l2_src_h;
1121
1122        /* ... and use the same setup routine as ivtv_yuv_prep_frame */
1123        ivtv_yuv_setup_frame(itv, &dma_args);
1124
1125        if (!itv->dma_data_req_offset)
1126                itv->dma_data_req_offset = yuv_offset[yi->draw_frame];
1127}
1128
1129/* Attempt to dma a frame from a user buffer */
1130int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
1131{
1132        struct yuv_playback_info *yi = &itv->yuv_info;
1133        struct ivtv_dma_frame dma_args;
1134        int res;
1135
1136        ivtv_yuv_setup_stream_frame(itv);
1137
1138        /* We only need to supply source addresses for this */
1139        dma_args.y_source = src;
1140        dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
1141        /* Wait for frame DMA. Note that serialize_lock is locked,
1142           so to allow other processes to access the driver while
1143           we are waiting unlock first and later lock again. */
1144        mutex_unlock(&itv->serialize_lock);
1145        res = ivtv_yuv_udma_frame(itv, &dma_args);
1146        mutex_lock(&itv->serialize_lock);
1147        return res;
1148}
1149
1150/* IVTV_IOC_DMA_FRAME ioctl handler */
1151int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
1152{
1153        int res;
1154
1155/*      IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
1156        ivtv_yuv_next_free(itv);
1157        ivtv_yuv_setup_frame(itv, args);
1158        /* Wait for frame DMA. Note that serialize_lock is locked,
1159           so to allow other processes to access the driver while
1160           we are waiting unlock first and later lock again. */
1161        mutex_unlock(&itv->serialize_lock);
1162        res = ivtv_yuv_udma_frame(itv, args);
1163        mutex_lock(&itv->serialize_lock);
1164        return res;
1165}
1166
1167void ivtv_yuv_close(struct ivtv *itv)
1168{
1169        struct yuv_playback_info *yi = &itv->yuv_info;
1170        int h_filter, v_filter_1, v_filter_2;
1171
1172        IVTV_DEBUG_YUV("ivtv_yuv_close\n");
1173        mutex_unlock(&itv->serialize_lock);
1174        ivtv_waitq(&itv->vsync_waitq);
1175        mutex_lock(&itv->serialize_lock);
1176
1177        yi->running = 0;
1178        atomic_set(&yi->next_dma_frame, -1);
1179        atomic_set(&yi->next_fill_frame, 0);
1180
1181        /* Reset registers we have changed so mpeg playback works */
1182
1183        /* If we fully restore this register, the display may remain active.
1184           Restore, but set one bit to blank the video. Firmware will always
1185           clear this bit when needed, so not a problem. */
1186        write_reg(yi->reg_2898 | 0x01000000, 0x2898);
1187
1188        write_reg(yi->reg_2834, 0x02834);
1189        write_reg(yi->reg_2838, 0x02838);
1190        write_reg(yi->reg_283c, 0x0283c);
1191        write_reg(yi->reg_2840, 0x02840);
1192        write_reg(yi->reg_2844, 0x02844);
1193        write_reg(yi->reg_2848, 0x02848);
1194        write_reg(yi->reg_2854, 0x02854);
1195        write_reg(yi->reg_285c, 0x0285c);
1196        write_reg(yi->reg_2864, 0x02864);
1197        write_reg(yi->reg_2870, 0x02870);
1198        write_reg(yi->reg_2874, 0x02874);
1199        write_reg(yi->reg_2890, 0x02890);
1200        write_reg(yi->reg_289c, 0x0289c);
1201
1202        write_reg(yi->reg_2918, 0x02918);
1203        write_reg(yi->reg_291c, 0x0291c);
1204        write_reg(yi->reg_2920, 0x02920);
1205        write_reg(yi->reg_2924, 0x02924);
1206        write_reg(yi->reg_2928, 0x02928);
1207        write_reg(yi->reg_292c, 0x0292c);
1208        write_reg(yi->reg_2930, 0x02930);
1209        write_reg(yi->reg_2934, 0x02934);
1210        write_reg(yi->reg_2938, 0x02938);
1211        write_reg(yi->reg_293c, 0x0293c);
1212        write_reg(yi->reg_2940, 0x02940);
1213        write_reg(yi->reg_2944, 0x02944);
1214        write_reg(yi->reg_2948, 0x02948);
1215        write_reg(yi->reg_294c, 0x0294c);
1216        write_reg(yi->reg_2950, 0x02950);
1217        write_reg(yi->reg_2954, 0x02954);
1218        write_reg(yi->reg_2958, 0x02958);
1219        write_reg(yi->reg_295c, 0x0295c);
1220        write_reg(yi->reg_2960, 0x02960);
1221        write_reg(yi->reg_2964, 0x02964);
1222        write_reg(yi->reg_2968, 0x02968);
1223        write_reg(yi->reg_296c, 0x0296c);
1224        write_reg(yi->reg_2970, 0x02970);
1225
1226        /* Prepare to restore filters */
1227
1228        /* First the horizontal filter */
1229        if ((yi->reg_2834 & 0x0000FFFF) == (yi->reg_2834 >> 16)) {
1230                /* An exact size match uses filter 0 */
1231                h_filter = 0;
1232        } else {
1233                /* Figure out which filter to use */
1234                h_filter = ((yi->reg_2834 << 16) / (yi->reg_2834 >> 16)) >> 15;
1235                h_filter = (h_filter >> 1) + (h_filter & 1);
1236                /* Only an exact size match can use filter 0. */
1237                h_filter += !h_filter;
1238        }
1239
1240        /* Now the vertical filter */
1241        if ((yi->reg_2918 & 0x0000FFFF) == (yi->reg_2918 >> 16)) {
1242                /* An exact size match uses filter 0/1 */
1243                v_filter_1 = 0;
1244                v_filter_2 = 1;
1245        } else {
1246                /* Figure out which filter to use */
1247                v_filter_1 = ((yi->reg_2918 << 16) / (yi->reg_2918 >> 16)) >> 15;
1248                v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
1249                /* Only an exact size match can use filter 0 */
1250                v_filter_1 += !v_filter_1;
1251                v_filter_2 = v_filter_1;
1252        }
1253
1254        /* Now restore the filters */
1255        ivtv_yuv_filter(itv, h_filter, v_filter_1, v_filter_2);
1256
1257        /* and clear a few registers */
1258        write_reg(0, 0x02814);
1259        write_reg(0, 0x0282c);
1260        write_reg(0, 0x02904);
1261        write_reg(0, 0x02910);
1262
1263        /* Release the blanking buffer */
1264        if (yi->blanking_ptr) {
1265                kfree(yi->blanking_ptr);
1266                yi->blanking_ptr = NULL;
1267                pci_unmap_single(itv->pdev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE);
1268        }
1269
1270        /* Invalidate the old dimension information */
1271        yi->old_frame_info.src_w = 0;
1272        yi->old_frame_info.src_h = 0;
1273        yi->old_frame_info_args.src_w = 0;
1274        yi->old_frame_info_args.src_h = 0;
1275
1276        /* All done. */
1277        clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
1278}
1279