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