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