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