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