aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/v4l2-core/v4l2-dv-timings.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-dv-timings.c')
-rw-r--r--drivers/media/v4l2-core/v4l2-dv-timings.c117
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
29MODULE_AUTHOR("Hans Verkuil"); 30MODULE_AUTHOR("Hans Verkuil");
30MODULE_DESCRIPTION("V4L2 DV Timings Helper Functions"); 31MODULE_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 */
350bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync, 360bool 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}
460EXPORT_SYMBOL_GPL(v4l2_detect_cvt); 496EXPORT_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}
581EXPORT_SYMBOL_GPL(v4l2_detect_gtf); 654EXPORT_SYMBOL_GPL(v4l2_detect_gtf);