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