diff options
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-dv-timings.c')
-rw-r--r-- | drivers/media/v4l2-core/v4l2-dv-timings.c | 117 |
1 files changed, 95 insertions, 22 deletions
diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c index c0e96382feba..04dc71e3ebf0 100644 --- a/drivers/media/v4l2-core/v4l2-dv-timings.c +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/videodev2.h> | 25 | #include <linux/videodev2.h> |
26 | #include <linux/v4l2-dv-timings.h> | 26 | #include <linux/v4l2-dv-timings.h> |
27 | #include <media/v4l2-dv-timings.h> | 27 | #include <media/v4l2-dv-timings.h> |
28 | #include <linux/math64.h> | ||
28 | 29 | ||
29 | MODULE_AUTHOR("Hans Verkuil"); | 30 | MODULE_AUTHOR("Hans Verkuil"); |
30 | MODULE_DESCRIPTION("V4L2 DV Timings Helper Functions"); | 31 | MODULE_DESCRIPTION("V4L2 DV Timings Helper Functions"); |
@@ -261,6 +262,8 @@ void v4l2_print_dv_timings(const char *dev_prefix, const char *prefix, | |||
261 | 262 | ||
262 | htot = V4L2_DV_BT_FRAME_WIDTH(bt); | 263 | htot = V4L2_DV_BT_FRAME_WIDTH(bt); |
263 | vtot = V4L2_DV_BT_FRAME_HEIGHT(bt); | 264 | vtot = V4L2_DV_BT_FRAME_HEIGHT(bt); |
265 | if (bt->interlaced) | ||
266 | vtot /= 2; | ||
264 | 267 | ||
265 | if (prefix == NULL) | 268 | if (prefix == NULL) |
266 | prefix = ""; | 269 | prefix = ""; |
@@ -281,6 +284,11 @@ void v4l2_print_dv_timings(const char *dev_prefix, const char *prefix, | |||
281 | dev_prefix, bt->vfrontporch, | 284 | dev_prefix, bt->vfrontporch, |
282 | (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-", | 285 | (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-", |
283 | bt->vsync, bt->vbackporch); | 286 | bt->vsync, bt->vbackporch); |
287 | if (bt->interlaced) | ||
288 | pr_info("%s: vertical bottom field: fp = %u, %ssync = %u, bp = %u\n", | ||
289 | dev_prefix, bt->il_vfrontporch, | ||
290 | (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-", | ||
291 | bt->il_vsync, bt->il_vbackporch); | ||
284 | pr_info("%s: pixelclock: %llu\n", dev_prefix, bt->pixelclock); | 292 | pr_info("%s: pixelclock: %llu\n", dev_prefix, bt->pixelclock); |
285 | pr_info("%s: flags (0x%x):%s%s%s%s%s\n", dev_prefix, bt->flags, | 293 | pr_info("%s: flags (0x%x):%s%s%s%s%s\n", dev_prefix, bt->flags, |
286 | (bt->flags & V4L2_DV_FL_REDUCED_BLANKING) ? | 294 | (bt->flags & V4L2_DV_FL_REDUCED_BLANKING) ? |
@@ -313,6 +321,7 @@ EXPORT_SYMBOL_GPL(v4l2_print_dv_timings); | |||
313 | #define CVT_MIN_V_BPORCH 7 /* lines */ | 321 | #define CVT_MIN_V_BPORCH 7 /* lines */ |
314 | #define CVT_MIN_V_PORCH_RND 3 /* lines */ | 322 | #define CVT_MIN_V_PORCH_RND 3 /* lines */ |
315 | #define CVT_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */ | 323 | #define CVT_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */ |
324 | #define CVT_HSYNC_PERCENT 8 /* nominal hsync as percentage of line */ | ||
316 | 325 | ||
317 | /* Normal blanking for CVT uses GTF to calculate horizontal blanking */ | 326 | /* Normal blanking for CVT uses GTF to calculate horizontal blanking */ |
318 | #define CVT_CELL_GRAN 8 /* character cell granularity */ | 327 | #define CVT_CELL_GRAN 8 /* character cell granularity */ |
@@ -337,6 +346,7 @@ EXPORT_SYMBOL_GPL(v4l2_print_dv_timings); | |||
337 | * @vsync - the height of the vertical sync in lines. | 346 | * @vsync - the height of the vertical sync in lines. |
338 | * @polarities - the horizontal and vertical polarities (same as struct | 347 | * @polarities - the horizontal and vertical polarities (same as struct |
339 | * v4l2_bt_timings polarities). | 348 | * v4l2_bt_timings polarities). |
349 | * @interlaced - if this flag is true, it indicates interlaced format | ||
340 | * @fmt - the resulting timings. | 350 | * @fmt - the resulting timings. |
341 | * | 351 | * |
342 | * This function will attempt to detect if the given values correspond to a | 352 | * This function will attempt to detect if the given values correspond to a |
@@ -348,7 +358,7 @@ EXPORT_SYMBOL_GPL(v4l2_print_dv_timings); | |||
348 | * detection function. | 358 | * detection function. |
349 | */ | 359 | */ |
350 | bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync, | 360 | bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync, |
351 | u32 polarities, struct v4l2_dv_timings *fmt) | 361 | u32 polarities, bool interlaced, struct v4l2_dv_timings *fmt) |
352 | { | 362 | { |
353 | int v_fp, v_bp, h_fp, h_bp, hsync; | 363 | int v_fp, v_bp, h_fp, h_bp, hsync; |
354 | int frame_width, image_height, image_width; | 364 | int frame_width, image_height, image_width; |
@@ -365,22 +375,32 @@ bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync, | |||
365 | else | 375 | else |
366 | return false; | 376 | return false; |
367 | 377 | ||
378 | if (hfreq == 0) | ||
379 | return false; | ||
380 | |||
368 | /* Vertical */ | 381 | /* Vertical */ |
369 | if (reduced_blanking) { | 382 | if (reduced_blanking) { |
370 | v_fp = CVT_RB_V_FPORCH; | 383 | v_fp = CVT_RB_V_FPORCH; |
371 | v_bp = (CVT_RB_MIN_V_BLANK * hfreq + 1999999) / 1000000; | 384 | v_bp = (CVT_RB_MIN_V_BLANK * hfreq) / 1000000 + 1; |
372 | v_bp -= vsync + v_fp; | 385 | v_bp -= vsync + v_fp; |
373 | 386 | ||
374 | if (v_bp < CVT_RB_MIN_V_BPORCH) | 387 | if (v_bp < CVT_RB_MIN_V_BPORCH) |
375 | v_bp = CVT_RB_MIN_V_BPORCH; | 388 | v_bp = CVT_RB_MIN_V_BPORCH; |
376 | } else { | 389 | } else { |
377 | v_fp = CVT_MIN_V_PORCH_RND; | 390 | v_fp = CVT_MIN_V_PORCH_RND; |
378 | v_bp = (CVT_MIN_VSYNC_BP * hfreq + 1999999) / 1000000 - vsync; | 391 | v_bp = (CVT_MIN_VSYNC_BP * hfreq) / 1000000 + 1 - vsync; |
379 | 392 | ||
380 | if (v_bp < CVT_MIN_V_BPORCH) | 393 | if (v_bp < CVT_MIN_V_BPORCH) |
381 | v_bp = CVT_MIN_V_BPORCH; | 394 | v_bp = CVT_MIN_V_BPORCH; |
382 | } | 395 | } |
383 | image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1; | 396 | |
397 | if (interlaced) | ||
398 | image_height = (frame_height - 2 * v_fp - 2 * vsync - 2 * v_bp) & ~0x1; | ||
399 | else | ||
400 | image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1; | ||
401 | |||
402 | if (image_height < 0) | ||
403 | return false; | ||
384 | 404 | ||
385 | /* Aspect ratio based on vsync */ | 405 | /* Aspect ratio based on vsync */ |
386 | switch (vsync) { | 406 | switch (vsync) { |
@@ -436,8 +456,8 @@ bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync, | |||
436 | h_bp = h_blank / 2; | 456 | h_bp = h_blank / 2; |
437 | frame_width = image_width + h_blank; | 457 | frame_width = image_width + h_blank; |
438 | 458 | ||
439 | hsync = (frame_width * 8 + 50) / 100; | 459 | hsync = frame_width * CVT_HSYNC_PERCENT / 100; |
440 | hsync = hsync - hsync % CVT_CELL_GRAN; | 460 | hsync = (hsync / CVT_CELL_GRAN) * CVT_CELL_GRAN; |
441 | h_fp = h_blank - hsync - h_bp; | 461 | h_fp = h_blank - hsync - h_bp; |
442 | } | 462 | } |
443 | 463 | ||
@@ -450,11 +470,27 @@ bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync, | |||
450 | fmt->bt.hsync = hsync; | 470 | fmt->bt.hsync = hsync; |
451 | fmt->bt.vsync = vsync; | 471 | fmt->bt.vsync = vsync; |
452 | fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync; | 472 | fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync; |
453 | fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync; | 473 | |
474 | if (!interlaced) { | ||
475 | fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync; | ||
476 | fmt->bt.interlaced = V4L2_DV_PROGRESSIVE; | ||
477 | } else { | ||
478 | fmt->bt.vbackporch = (frame_height - image_height - 2 * v_fp - | ||
479 | 2 * vsync) / 2; | ||
480 | fmt->bt.il_vbackporch = frame_height - image_height - 2 * v_fp - | ||
481 | 2 * vsync - fmt->bt.vbackporch; | ||
482 | fmt->bt.il_vfrontporch = v_fp; | ||
483 | fmt->bt.il_vsync = vsync; | ||
484 | fmt->bt.flags |= V4L2_DV_FL_HALF_LINE; | ||
485 | fmt->bt.interlaced = V4L2_DV_INTERLACED; | ||
486 | } | ||
487 | |||
454 | fmt->bt.pixelclock = pix_clk; | 488 | fmt->bt.pixelclock = pix_clk; |
455 | fmt->bt.standards = V4L2_DV_BT_STD_CVT; | 489 | fmt->bt.standards = V4L2_DV_BT_STD_CVT; |
490 | |||
456 | if (reduced_blanking) | 491 | if (reduced_blanking) |
457 | fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING; | 492 | fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING; |
493 | |||
458 | return true; | 494 | return true; |
459 | } | 495 | } |
460 | EXPORT_SYMBOL_GPL(v4l2_detect_cvt); | 496 | EXPORT_SYMBOL_GPL(v4l2_detect_cvt); |
@@ -493,6 +529,7 @@ EXPORT_SYMBOL_GPL(v4l2_detect_cvt); | |||
493 | * @vsync - the height of the vertical sync in lines. | 529 | * @vsync - the height of the vertical sync in lines. |
494 | * @polarities - the horizontal and vertical polarities (same as struct | 530 | * @polarities - the horizontal and vertical polarities (same as struct |
495 | * v4l2_bt_timings polarities). | 531 | * v4l2_bt_timings polarities). |
532 | * @interlaced - if this flag is true, it indicates interlaced format | ||
496 | * @aspect - preferred aspect ratio. GTF has no method of determining the | 533 | * @aspect - preferred aspect ratio. GTF has no method of determining the |
497 | * aspect ratio in order to derive the image width from the | 534 | * aspect ratio in order to derive the image width from the |
498 | * image height, so it has to be passed explicitly. Usually | 535 | * image height, so it has to be passed explicitly. Usually |
@@ -508,6 +545,7 @@ bool v4l2_detect_gtf(unsigned frame_height, | |||
508 | unsigned hfreq, | 545 | unsigned hfreq, |
509 | unsigned vsync, | 546 | unsigned vsync, |
510 | u32 polarities, | 547 | u32 polarities, |
548 | bool interlaced, | ||
511 | struct v4l2_fract aspect, | 549 | struct v4l2_fract aspect, |
512 | struct v4l2_dv_timings *fmt) | 550 | struct v4l2_dv_timings *fmt) |
513 | { | 551 | { |
@@ -527,10 +565,19 @@ bool v4l2_detect_gtf(unsigned frame_height, | |||
527 | else | 565 | else |
528 | return false; | 566 | return false; |
529 | 567 | ||
568 | if (hfreq == 0) | ||
569 | return false; | ||
570 | |||
530 | /* Vertical */ | 571 | /* Vertical */ |
531 | v_fp = GTF_V_FP; | 572 | v_fp = GTF_V_FP; |
532 | v_bp = (GTF_MIN_VSYNC_BP * hfreq + 999999) / 1000000 - vsync; | 573 | v_bp = (GTF_MIN_VSYNC_BP * hfreq + 500000) / 1000000 - vsync; |
533 | image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1; | 574 | if (interlaced) |
575 | image_height = (frame_height - 2 * v_fp - 2 * vsync - 2 * v_bp) & ~0x1; | ||
576 | else | ||
577 | image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1; | ||
578 | |||
579 | if (image_height < 0) | ||
580 | return false; | ||
534 | 581 | ||
535 | if (aspect.numerator == 0 || aspect.denominator == 0) { | 582 | if (aspect.numerator == 0 || aspect.denominator == 0) { |
536 | aspect.numerator = 16; | 583 | aspect.numerator = 16; |
@@ -540,25 +587,35 @@ bool v4l2_detect_gtf(unsigned frame_height, | |||
540 | image_width = (image_width + GTF_CELL_GRAN/2) & ~(GTF_CELL_GRAN - 1); | 587 | image_width = (image_width + GTF_CELL_GRAN/2) & ~(GTF_CELL_GRAN - 1); |
541 | 588 | ||
542 | /* Horizontal */ | 589 | /* Horizontal */ |
543 | if (default_gtf) | 590 | if (default_gtf) { |
544 | h_blank = ((image_width * GTF_D_C_PRIME * hfreq) - | 591 | u64 num; |
545 | (image_width * GTF_D_M_PRIME * 1000) + | 592 | u32 den; |
546 | (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) / 2) / | 593 | |
547 | (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000); | 594 | num = ((image_width * GTF_D_C_PRIME * (u64)hfreq) - |
548 | else | 595 | ((u64)image_width * GTF_D_M_PRIME * 1000)); |
549 | h_blank = ((image_width * GTF_S_C_PRIME * hfreq) - | 596 | den = (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) * |
550 | (image_width * GTF_S_M_PRIME * 1000) + | 597 | (2 * GTF_CELL_GRAN); |
551 | (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) / 2) / | 598 | h_blank = div_u64((num + (den >> 1)), den); |
552 | (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000); | 599 | h_blank *= (2 * GTF_CELL_GRAN); |
600 | } else { | ||
601 | u64 num; | ||
602 | u32 den; | ||
603 | |||
604 | num = ((image_width * GTF_S_C_PRIME * (u64)hfreq) - | ||
605 | ((u64)image_width * GTF_S_M_PRIME * 1000)); | ||
606 | den = (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) * | ||
607 | (2 * GTF_CELL_GRAN); | ||
608 | h_blank = div_u64((num + (den >> 1)), den); | ||
609 | h_blank *= (2 * GTF_CELL_GRAN); | ||
610 | } | ||
553 | 611 | ||
554 | h_blank = h_blank - h_blank % (2 * GTF_CELL_GRAN); | ||
555 | frame_width = image_width + h_blank; | 612 | frame_width = image_width + h_blank; |
556 | 613 | ||
557 | pix_clk = (image_width + h_blank) * hfreq; | 614 | pix_clk = (image_width + h_blank) * hfreq; |
558 | pix_clk = pix_clk / GTF_PXL_CLK_GRAN * GTF_PXL_CLK_GRAN; | 615 | pix_clk = pix_clk / GTF_PXL_CLK_GRAN * GTF_PXL_CLK_GRAN; |
559 | 616 | ||
560 | hsync = (frame_width * 8 + 50) / 100; | 617 | hsync = (frame_width * 8 + 50) / 100; |
561 | hsync = hsync - hsync % GTF_CELL_GRAN; | 618 | hsync = ((hsync + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN) * GTF_CELL_GRAN; |
562 | 619 | ||
563 | h_fp = h_blank / 2 - hsync; | 620 | h_fp = h_blank / 2 - hsync; |
564 | 621 | ||
@@ -571,11 +628,27 @@ bool v4l2_detect_gtf(unsigned frame_height, | |||
571 | fmt->bt.hsync = hsync; | 628 | fmt->bt.hsync = hsync; |
572 | fmt->bt.vsync = vsync; | 629 | fmt->bt.vsync = vsync; |
573 | fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync; | 630 | fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync; |
574 | fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync; | 631 | |
632 | if (!interlaced) { | ||
633 | fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync; | ||
634 | fmt->bt.interlaced = V4L2_DV_PROGRESSIVE; | ||
635 | } else { | ||
636 | fmt->bt.vbackporch = (frame_height - image_height - 2 * v_fp - | ||
637 | 2 * vsync) / 2; | ||
638 | fmt->bt.il_vbackporch = frame_height - image_height - 2 * v_fp - | ||
639 | 2 * vsync - fmt->bt.vbackporch; | ||
640 | fmt->bt.il_vfrontporch = v_fp; | ||
641 | fmt->bt.il_vsync = vsync; | ||
642 | fmt->bt.flags |= V4L2_DV_FL_HALF_LINE; | ||
643 | fmt->bt.interlaced = V4L2_DV_INTERLACED; | ||
644 | } | ||
645 | |||
575 | fmt->bt.pixelclock = pix_clk; | 646 | fmt->bt.pixelclock = pix_clk; |
576 | fmt->bt.standards = V4L2_DV_BT_STD_GTF; | 647 | fmt->bt.standards = V4L2_DV_BT_STD_GTF; |
648 | |||
577 | if (!default_gtf) | 649 | if (!default_gtf) |
578 | fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING; | 650 | fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING; |
651 | |||
579 | return true; | 652 | return true; |
580 | } | 653 | } |
581 | EXPORT_SYMBOL_GPL(v4l2_detect_gtf); | 654 | EXPORT_SYMBOL_GPL(v4l2_detect_gtf); |