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