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(¤t->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(¤t->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