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