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