linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Support for CVT, GTF timings
@ 2015-03-20  6:33 Prashant Laddha
  2015-03-20  6:33 ` [PATCH 1/3] v4l2-ctl: Add support for CVT, GTF modeline calculation Prashant Laddha
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Prashant Laddha @ 2015-03-20  6:33 UTC (permalink / raw)
  To: Linux Media Mailing List

These patches add support for calculating CVT and GTF timings in v4l2-ctl.

vl2-ctl already has a support setting up of fully specified timings. In
this case user needs to specify all values like pixel clock, sync, front
and back porches etc in v4l2_bt_timings structure. Hans had suggested
that it would be nice to add support for calculating CVT and GTF timings
in v4l2-ctl. I have been working with Hans on adding this support. Please
find following patches for the same.

0001-v4l2-ctl-Add-support-for-CVT-GTF-modeline-calculatio.patch
0002-v4l2-ctl-stds-Restructured-suboption-parsing-code.patch
0003-v4l2-ctl-stds-Support-cvt-gtf-options-in-set-dv-bt-t.patch

Please review and share your comments and suggestions.

Regards,
Prashant

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] v4l2-ctl: Add support for CVT, GTF modeline calculation
  2015-03-20  6:33 Support for CVT, GTF timings Prashant Laddha
@ 2015-03-20  6:33 ` Prashant Laddha
  2015-03-20 11:30   ` Hans Verkuil
  2015-03-20  6:33 ` [PATCH 2/3] v4l2-ctl-stds: Restructured suboption parsing code Prashant Laddha
  2015-03-20  6:33 ` [PATCH 3/3] v4l2-ctl-stds: Support cvt/gtf options in set-dv-bt-timings Prashant Laddha
  2 siblings, 1 reply; 7+ messages in thread
From: Prashant Laddha @ 2015-03-20  6:33 UTC (permalink / raw)
  To: Linux Media Mailing List; +Cc: Hans Verkuil, Prashant Laddha

This patch adds support for calculating v4l2_bt_timings based on
CVT and GTF standards. The timings are calculated for a given
standard, CVT or GTF using a set of parameters- width, height,
refresh rate and flags like whether it is an interlaced format,
and whether to use reduced blanking.

CVT Modeline calculation -
Implements Coordinated Video Timings (CVT) Standard Ver 1.2 Feb 08,
2013. The timing calculations are based on VESA CVT Generator Rev 1.2
by Graham Loveridge May 28, 2013.

GTF modeline calculation -
Implements Generalized Timing Formula (GTF) Standard Ver 1.1 Sept 02,
1999. The timing calculations are based on GTF timing spreadsheet by
Andy Morrish. The default GTF timings are used if flag for reduced
blanking is false, otherwise secondary GTF timings are used.

Suggested by: Hans Verkuil <hans.verkuil@cisco.com>

Cc: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Prashant Laddha <prladdha@cisco.com>
---
 utils/v4l2-ctl/Makefile.am        |   3 +-
 utils/v4l2-ctl/v4l2-ctl-modes.cpp | 512 ++++++++++++++++++++++++++++++++++++++
 utils/v4l2-ctl/v4l2-ctl.h         |   8 +
 3 files changed, 522 insertions(+), 1 deletion(-)
 create mode 100644 utils/v4l2-ctl/v4l2-ctl-modes.cpp

diff --git a/utils/v4l2-ctl/Makefile.am b/utils/v4l2-ctl/Makefile.am
index 29dd6cb..bc3f746 100644
--- a/utils/v4l2-ctl/Makefile.am
+++ b/utils/v4l2-ctl/Makefile.am
@@ -9,7 +9,8 @@ ivtv_ctl_LDFLAGS = -lm
 v4l2_ctl_SOURCES = v4l2-ctl.cpp v4l2-ctl.h v4l2-ctl-common.cpp v4l2-ctl-tuner.cpp \
 	v4l2-ctl-io.cpp v4l2-ctl-stds.cpp v4l2-ctl-vidcap.cpp v4l2-ctl-vidout.cpp \
 	v4l2-ctl-overlay.cpp v4l2-ctl-vbi.cpp v4l2-ctl-selection.cpp v4l2-ctl-misc.cpp \
-	v4l2-ctl-streaming.cpp v4l2-ctl-sdr.cpp v4l2-ctl-edid.cpp vivid-tpg-colors.c vivid-tpg.c
+	v4l2-ctl-streaming.cpp v4l2-ctl-sdr.cpp v4l2-ctl-edid.cpp v4l2-ctl-modes.cpp \
+	vivid-tpg-colors.c vivid-tpg.c
 v4l2_ctl_LDADD = ../../lib/libv4l2/libv4l2.la ../../lib/libv4lconvert/libv4lconvert.la
 v4l2_ctl_LDFLAGS = -lrt
 
diff --git a/utils/v4l2-ctl/v4l2-ctl-modes.cpp b/utils/v4l2-ctl/v4l2-ctl-modes.cpp
new file mode 100644
index 0000000..5157fea
--- /dev/null
+++ b/utils/v4l2-ctl/v4l2-ctl-modes.cpp
@@ -0,0 +1,512 @@
+/*
+ * v4l2-ctl-modes.cpp - functions to calculate cvt and gtf mode timings.
+ *
+ * Copyright 2015 Cisco Systems, Inc. and/or its affiliates. All rights
+ * reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include "v4l2-ctl.h"
+
+static bool valid_params(int width, int height, int refresh_rate)
+{
+	if (width <= 0) {
+		fprintf(stderr, "Invalid value %d for width\n", width);
+		return false;
+	}
+
+	if (height <= 0) {
+		fprintf(stderr, "Invalid value %d for height\n", height);
+		return false;
+	}
+
+	if (refresh_rate <= 0) {
+		fprintf(stderr, "Invalid value %d for refresh rate\n",
+				refresh_rate);
+		return false;
+	}
+	return true;
+}
+
+#define HV_FACTOR		(1000)
+#define CVT_MARGIN_PERCENT	  (18)
+#define CVT_HSYNC_PERCENT	   (8)
+
+/*
+ * CVT defines Based on
+ * Coordinated Video Timings Standard Ver 1.2 Feb 08, 2013
+ */
+
+#define CVT_PXL_CLK_GRAN    (250000)  /* pixel clock granularity */
+
+/* Normal blanking */
+#define CVT_MIN_V_BPORCH     (7)  /* lines */
+#define CVT_MIN_V_PORCH_RND  (3)  /* lines */
+#define CVT_MIN_VSYNC_BP    (550) /* time v_sync + back porch (us)*/
+
+/* Normal blanking for CVT uses GTF
+ * to calculate horizontal blanking */
+#define CVT_CELL_GRAN	(8)	  /* character cell granularity */
+#define CVT_M	      (600)	  /* blanking formula gradient */
+#define CVT_C	       (40)	  /* blanking formula offset */
+#define CVT_K	      (128)	  /* blanking formula scale factor */
+#define CVT_J	       (20)	  /* blanking formula scale factor */
+
+#define CVT_C_PRIME (((CVT_C - CVT_J) * CVT_K / 256) + CVT_J)
+#define CVT_M_PRIME (CVT_K * CVT_M / 256)
+
+/* Reduced Blanking */
+#define CVT_RB_MIN_V_BPORCH    (7)       /* lines  */
+#define CVT_RB_V_FPORCH        (3)       /* lines  */
+#define CVT_RB_MIN_V_BLANK   (460)       /* us     */
+#define CVT_RB_H_SYNC         (32)       /* pixels */
+#define CVT_RB_H_BPORCH       (80)       /* pixels */
+#define CVT_RB_H_BLANK       (160)       /* pixels */
+
+static int v_sync_from_aspect_ratio(int width, int height)
+{
+	if (((height * 4 / 3) / CVT_CELL_GRAN) * CVT_CELL_GRAN == width)
+		return 4;
+
+	if (((height * 16 / 9) / CVT_CELL_GRAN) * CVT_CELL_GRAN == width)
+		return 5;
+
+	if (((height * 16 / 10) / CVT_CELL_GRAN) * CVT_CELL_GRAN == width)
+		return 6;
+
+	if (((height * 5 / 4) / CVT_CELL_GRAN) * CVT_CELL_GRAN == width)
+		return 7;
+
+	if (((height * 15 / 9) / CVT_CELL_GRAN) * CVT_CELL_GRAN == width)
+		return 7;
+
+	/* custom aspect ratio */
+	fprintf(stderr, "Warning!  Aspect ratio is not CVT Standard\n");
+	return 10;
+}
+
+/**
+ * calc_cvt_modeline - calculate modeline based on CVT algorithm
+ *
+ * This function is called to generate the timings according to CVT
+ * algorithm. Timing calculation is based on VESA(TM) Coordinated
+ * Video Timing Generator Rev 1.2 by  Graham Loveridge May 28, 2013
+ * which can be downloaded from -
+ * http://www.vesa.org/vesa-standards/free-standards/
+ *
+ * Input Parameters:
+ * @image_width
+ * @image_height
+ * @refresh_rate
+ * @reduced_blanking: whether to use reduced blanking
+ * @interlaced: whether to compute an interlaced mode
+ * @cvt: stores results of cvt timing calculation
+ *
+ * Returns:
+ * true, if cvt timings are calculated and filled in cvt modeline.
+ * false, for any error
+ */
+
+bool calc_cvt_modeline(int image_width, int image_height,
+		       int refresh_rate, bool reduced_blanking,
+		       bool interlaced, struct v4l2_bt_timings *cvt)
+{
+	int h_sync;
+	int v_sync;
+	int h_fp;
+	int h_bp;
+	int v_fp;
+	int v_bp;
+
+	int h_pixel;
+	int v_lines;
+	int h_pixel_rnd;
+	int v_lines_rnd;
+	int active_h_pixel;
+	int active_v_lines;
+	int total_h_pixel;
+	int total_v_lines;
+
+	int h_blank;
+	int v_blank;
+
+	int h_period;
+
+	int interlace;
+	int v_refresh;
+	int pixel_clock;
+
+	if (!valid_params(image_width, image_height, refresh_rate))
+		return false;
+
+	h_pixel = image_width;
+	v_lines = image_height;
+
+	if (!refresh_rate)
+		v_refresh = 60;
+	else
+		v_refresh = refresh_rate;
+
+	if (v_refresh != 50 && v_refresh != 60 &&
+		v_refresh != 75 && v_refresh != 85)
+		fprintf(stderr, "Warning!  Refresh rate is not CVT standard\n");
+
+	if (interlaced) {
+		interlace = 1;
+		v_lines_rnd = v_lines / 2;
+		v_refresh = v_refresh * 2;
+
+		if ((v_lines_rnd * 2) != v_lines)
+			fprintf(stderr,
+			"Warning!  Vertical lines rounded to nearest integer\n");
+	} else {
+		interlace = 0;
+		v_lines_rnd = v_lines;
+	}
+
+	h_pixel_rnd = h_pixel - (h_pixel % CVT_CELL_GRAN);
+
+	if (h_pixel_rnd != h_pixel)
+		fprintf(stderr,
+		"Warning!  Horizontal pixels rounded to nearest character cell\n");
+
+	active_h_pixel = h_pixel_rnd;
+	active_v_lines = v_lines_rnd;
+
+	v_sync = v_sync_from_aspect_ratio(h_pixel, v_lines);
+
+	if (!reduced_blanking) {
+		int tmp1, tmp2;
+		int ideal_blank_duty_cycle;
+		int v_sync_bp;
+
+		/* estimate the horizontal period */
+		tmp1 = HV_FACTOR * 1000000  -
+			   CVT_MIN_VSYNC_BP * HV_FACTOR * v_refresh;
+		tmp2 = (active_v_lines + CVT_MIN_V_PORCH_RND) * 2 + interlace;
+
+		h_period = tmp1 * 2 / (tmp2 * v_refresh);
+
+		tmp1 = CVT_MIN_VSYNC_BP * HV_FACTOR / h_period + 1;
+
+		if (tmp1 < (v_sync + CVT_MIN_V_PORCH_RND))
+			v_sync_bp = v_sync + CVT_MIN_V_PORCH_RND;
+		else
+			v_sync_bp = tmp1;
+
+		v_bp = v_sync_bp - v_sync;
+		v_fp = CVT_MIN_V_PORCH_RND;
+
+		ideal_blank_duty_cycle = (CVT_C_PRIME * HV_FACTOR) -
+					  CVT_M_PRIME * h_period / 1000;
+
+		if (ideal_blank_duty_cycle < 20 * HV_FACTOR)
+			ideal_blank_duty_cycle = 20 * HV_FACTOR;
+
+		h_blank = active_h_pixel * ideal_blank_duty_cycle /
+			 (100 * HV_FACTOR - ideal_blank_duty_cycle);
+		h_blank -= h_blank % (2 * CVT_CELL_GRAN);
+
+		v_blank = v_sync_bp + CVT_MIN_V_PORCH_RND;
+
+		total_v_lines = active_v_lines + v_blank + interlace;
+		total_h_pixel = active_h_pixel + h_blank;
+
+		h_sync  = (total_h_pixel * CVT_HSYNC_PERCENT) / 100;
+		h_sync -= h_sync % CVT_CELL_GRAN;
+
+		h_bp = h_blank / 2;
+		h_fp = h_blank - h_bp - h_sync;
+
+	} else {
+		/* Reduced blanking */
+
+		int vbi_lines;
+		int tmp1, tmp2;
+
+		/* estimate horizontal period. */
+		tmp1 = HV_FACTOR * 1000000 -
+			   CVT_RB_MIN_V_BLANK * HV_FACTOR * v_refresh;
+		tmp2 = active_v_lines;
+
+		h_period = tmp1 / (tmp2 * v_refresh);
+
+		vbi_lines = CVT_RB_MIN_V_BLANK * HV_FACTOR / h_period + 1;
+
+		if (vbi_lines < (CVT_RB_V_FPORCH + v_sync + CVT_MIN_V_BPORCH))
+			vbi_lines = CVT_RB_V_FPORCH + v_sync + CVT_MIN_V_BPORCH;
+
+		total_v_lines = active_v_lines + vbi_lines;
+
+		total_h_pixel = active_h_pixel + CVT_RB_H_BLANK;
+
+		h_blank = CVT_RB_H_BLANK;
+		v_blank = vbi_lines;
+
+		h_sync = CVT_RB_H_SYNC;
+
+		h_bp = h_blank / 2;
+		h_fp = h_blank - h_bp - h_sync;
+
+		v_fp = CVT_RB_V_FPORCH;
+		v_bp = v_blank - v_fp - v_sync;
+	}
+
+	pixel_clock =  ((long long)total_h_pixel * HV_FACTOR * 1000000)
+			/ h_period;
+	pixel_clock -= pixel_clock  % CVT_PXL_CLK_GRAN;
+
+	cvt->standards 	 = V4L2_DV_BT_STD_CVT;
+
+	cvt->width       = h_pixel;
+	cvt->hfrontporch = h_fp;
+	cvt->hsync       = h_sync;
+	cvt->hbackporch  = h_bp;
+
+	cvt->height      = v_lines;
+	cvt->vfrontporch = v_fp;
+	cvt->vsync       = v_sync;
+	cvt->vbackporch  = v_bp;
+
+	cvt->pixelclock = pixel_clock;
+	cvt->interlaced = interlaced == 1 ?
+			V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
+
+	if (cvt->interlaced == V4L2_DV_INTERLACED) {
+		cvt->il_vfrontporch = v_fp;
+		cvt->il_vsync = v_sync;
+		cvt->il_vbackporch = v_bp;
+		/* For interlaced format, add half lines to front and back
+		 * porches of odd and even fields respectively */
+		cvt->flags |= V4L2_DV_FL_HALF_LINE;
+		cvt->vfrontporch += 1;
+		cvt->il_vbackporch += 1;
+	}
+	if (reduced_blanking) {
+		cvt->polarities = V4L2_DV_HSYNC_POS_POL;
+		cvt->flags |= V4L2_DV_FL_REDUCED_BLANKING;
+	} else
+		cvt->polarities = V4L2_DV_VSYNC_POS_POL;
+
+	return true;
+}
+
+
+/*
+ * GTF defines Based on Generalized Timing Formula Standard
+ * Version 1.1 September 2, 1999
+ */
+
+#define GTF_MARGIN_PERCENT	  (18)
+#define GTF_HSYNC_PERCENT	   (8)
+
+#define GTF_PXL_CLK_GRAN (250000) /* pixel clock granularity */
+
+#define GTF_V_SYNC_RQD	   (3) /* v sync required (lines) */
+#define GTF_MIN_VSYNC_BP (550) /* min time vsync + back porch (us) */
+#define GTF_MIN_PORCH	   (1) /* vertical front porch (lines) */
+#define GTF_CELL_GRAN      (8) /* character cell granularity */
+
+/* Default */
+#define GTF_D_M		(600)	 /* blanking formula gradient */
+#define GTF_D_C		 (40)    /* blanking formula offset */
+#define GTF_D_K		(128)	 /* blanking formula scaling factor */
+#define GTF_D_J		 (20)	 /* blanking formula scaling factor */
+#define GTF_D_C_PRIME ((((GTF_D_C - GTF_D_J) * GTF_D_K) / 256) + GTF_D_J)
+#define GTF_D_M_PRIME ((GTF_D_K * GTF_D_M) / 256)
+
+/* Secondary */
+#define GTF_S_M		 (3600)	    /* blanking formula gradient */
+#define GTF_S_C		   (40)	    /* blanking formula offset */
+#define GTF_S_K		  (128)	    /* blanking formula scaling factor */
+#define GTF_S_J		   (35)	    /* blanking formula scaling factor */
+#define GTF_S_C_PRIME ((((GTF_S_C - GTF_S_J) * GTF_S_K) / 256) + GTF_S_J)
+#define GTF_S_M_PRIME ((GTF_S_K * GTF_S_M) / 256)
+
+/**
+ * calc_gtf_modeline - calculate modeline based on GTF algorithm
+ *
+ * This function is called to generate the timings according to GTF
+ * algorithm. Timing calculation is based on VESA(TM) Generalized
+ * Timing Formula Standard Version 1.1 September 2, 1999
+ * which can be downloaded from -
+ * http://www.vesa.org/vesa-standards/free-standards/
+ *
+ * Input Parameters:
+ * @image_width
+ * @image_height
+ * @refresh_rate
+ * @reduced_blanking: whether to use reduced blanking
+ * @interlaced: whether to compute an interlaced mode
+ * @gtf: stores results of gtf timing calculation
+ *
+ * Returns:
+ * true, if gtf timings are calculated and filled in gtf modeline.
+ * false, for any error.
+ */
+
+bool calc_gtf_modeline(int image_width, int image_height,
+		       int refresh_rate, bool reduced_blanking,
+		       bool interlaced, struct v4l2_bt_timings *gtf)
+{
+	int h_sync;
+	int v_sync;
+	int h_fp;
+	int h_bp;
+	int v_fp;
+	int v_bp;
+
+	int h_pixel;
+	int v_lines;
+	int h_pixel_rnd;
+	int v_lines_rnd;
+	int active_h_pixel;
+	int active_v_lines;
+	int total_h_pixel;
+	int total_v_lines;
+
+	int h_blank;
+	int v_blank;
+
+	int h_period;
+	int h_period_est;
+
+	int interlace;
+	int v_refresh;
+	int v_refresh_est;
+	int pixel_clock;
+
+	int v_sync_bp;
+	int tmp1, tmp2;
+	int ideal_blank_duty_cycle;
+
+	if (!gtf) {
+		fprintf(stderr, "Null pointer to gtf modeline structure\n");
+		return false;
+	}
+
+	if (!valid_params(image_width, image_height, refresh_rate))
+		return false;
+
+	h_pixel = image_width;
+	v_lines = image_height;
+
+	if (!refresh_rate)
+		v_refresh = 60;
+	else
+		v_refresh = refresh_rate;
+
+	if (interlaced) {
+		interlace = 1;
+		v_lines_rnd = v_lines / 2;
+		v_refresh = v_refresh * 2;
+	} else {
+		interlace = 0;
+		v_lines_rnd = v_lines;
+	}
+
+	h_pixel_rnd = (h_pixel + GTF_CELL_GRAN / 2);
+	h_pixel_rnd -= h_pixel_rnd % GTF_CELL_GRAN;
+
+	active_h_pixel = h_pixel_rnd;
+	active_v_lines = v_lines_rnd;
+
+		/* estimate the horizontal period */
+	tmp1 = HV_FACTOR * 1000000  -
+		   GTF_MIN_VSYNC_BP * HV_FACTOR * v_refresh;
+	tmp2 = active_v_lines + GTF_MIN_PORCH + interlace;
+
+	h_period_est = tmp1 / (tmp2 * v_refresh);
+
+	v_sync_bp = GTF_MIN_VSYNC_BP * HV_FACTOR * 100 / h_period_est;
+	v_sync_bp = (v_sync_bp + 50) / 100;
+
+	v_sync = GTF_V_SYNC_RQD;
+	v_bp = v_sync_bp - v_sync;
+	v_fp = GTF_MIN_PORCH;
+
+	v_blank = v_sync + v_bp + v_fp;
+	total_v_lines = active_v_lines + v_blank + interlace;
+
+	v_refresh_est = (HV_FACTOR * (long long)1000000) /
+			(h_period_est * total_v_lines / HV_FACTOR);
+
+	h_period = (h_period_est * v_refresh_est) /
+		   (v_refresh * HV_FACTOR);
+
+	if (!reduced_blanking)
+		ideal_blank_duty_cycle = (GTF_D_C_PRIME * HV_FACTOR) -
+				      GTF_D_M_PRIME * h_period / 1000;
+	else
+		ideal_blank_duty_cycle = (GTF_S_C_PRIME * HV_FACTOR) -
+				      GTF_S_M_PRIME * h_period / 1000;
+
+
+	h_blank = active_h_pixel * ideal_blank_duty_cycle /
+			 (100 * HV_FACTOR - ideal_blank_duty_cycle);
+	h_blank -= h_blank % (2 * GTF_CELL_GRAN);
+
+	total_h_pixel = active_h_pixel + h_blank;
+
+	h_sync  = (total_h_pixel * GTF_HSYNC_PERCENT) / 100;
+	h_sync -= h_sync % GTF_CELL_GRAN;
+
+	h_fp = h_blank / 2 - h_sync;
+	h_bp = h_fp + h_sync;
+
+	pixel_clock = ((long long)total_h_pixel * HV_FACTOR * 1000000)
+					/ h_period;
+	/* Not sure if clock value needs to be truncated to multiple
+	 * of 25000. The formula given in standard does not indicate
+	 * truncation
+	 * */
+	/*pixel_clock -= pixel_clock  % GTF_PXL_CLK_GRAN;*/
+
+	gtf->standards 	 = V4L2_DV_BT_STD_GTF;
+
+	gtf->width       = h_pixel;
+	gtf->hfrontporch = h_fp;
+	gtf->hsync       = h_sync;
+	gtf->hbackporch  = h_bp;
+
+	gtf->height      = v_lines;
+	gtf->vfrontporch = v_fp;
+	gtf->vsync       = v_sync;
+	gtf->vbackporch  = v_bp;
+
+	gtf->pixelclock = pixel_clock;
+	gtf->interlaced = interlaced == 1 ?
+			V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
+
+	if (gtf->interlaced == V4L2_DV_INTERLACED) {
+		gtf->il_vfrontporch = v_fp;
+		gtf->il_vsync = v_sync;
+		gtf->il_vbackporch = v_bp;
+		/* For interlaced format, add half lines to front and back
+		 * porches of odd and even fields respectively */
+		gtf->flags |= V4L2_DV_FL_HALF_LINE;
+		gtf->vfrontporch += 1;
+		gtf->il_vbackporch += 1;
+	}
+	if (reduced_blanking) {
+		gtf->polarities = V4L2_DV_HSYNC_POS_POL;
+		gtf->flags |= V4L2_DV_FL_REDUCED_BLANKING;
+	} else
+		gtf->polarities = V4L2_DV_VSYNC_POS_POL;
+
+	return true;
+}
diff --git a/utils/v4l2-ctl/v4l2-ctl.h b/utils/v4l2-ctl/v4l2-ctl.h
index f8b3df2..e47612f 100644
--- a/utils/v4l2-ctl/v4l2-ctl.h
+++ b/utils/v4l2-ctl/v4l2-ctl.h
@@ -347,4 +347,12 @@ void edid_cmd(int ch, char *optarg);
 void edid_set(int fd);
 void edid_get(int fd);
 
+/* v4l2-ctl-modes.cpp */
+bool calc_cvt_modeline(int image_width, int image_height,
+		       int refresh_rate, bool reduced_blanking,
+		       bool interlaced, struct v4l2_bt_timings *cvt);
+
+bool calc_gtf_modeline(int image_width, int image_height,
+		       int refresh_rate, bool reduced_blanking,
+		       bool interlaced, struct v4l2_bt_timings *gtf);
 #endif
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] v4l2-ctl-stds: Restructured suboption parsing code
  2015-03-20  6:33 Support for CVT, GTF timings Prashant Laddha
  2015-03-20  6:33 ` [PATCH 1/3] v4l2-ctl: Add support for CVT, GTF modeline calculation Prashant Laddha
@ 2015-03-20  6:33 ` Prashant Laddha
  2015-03-20  6:33 ` [PATCH 3/3] v4l2-ctl-stds: Support cvt/gtf options in set-dv-bt-timings Prashant Laddha
  2 siblings, 0 replies; 7+ messages in thread
From: Prashant Laddha @ 2015-03-20  6:33 UTC (permalink / raw)
  To: Linux Media Mailing List; +Cc: Hans Verkuil, Prashant Laddha

This change is in preparation towards extending suboptions to include
options to set cvt/gtf timings. One of the suboption for cvt/gtf is
without value. The existing function parse_subopt() does not support
parsing of suboption without value.

Replacing parse_subopt() with new function parse_timing_subopt(). In
fact, parse_subopt() is a wrapper around getsubopt() and parse_subopt()
can be modified to support suboptions without value. However, avoided
such a change because it would have led to changes in some more files.

Also, enumerated sub options. This would make it easier to add/remove
suboptions for cvt, gtf.

Cc: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Prashant Laddha <prladdha@cisco.com>
---
 utils/v4l2-ctl/v4l2-ctl-stds.cpp | 149 +++++++++++++++++++++++++--------------
 1 file changed, 97 insertions(+), 52 deletions(-)

diff --git a/utils/v4l2-ctl/v4l2-ctl-stds.cpp b/utils/v4l2-ctl/v4l2-ctl-stds.cpp
index 4c7e308..2141876 100644
--- a/utils/v4l2-ctl/v4l2-ctl-stds.cpp
+++ b/utils/v4l2-ctl/v4l2-ctl-stds.cpp
@@ -20,7 +20,7 @@ static v4l2_std_id standard;		/* get_std/set_std */
 static struct v4l2_dv_timings dv_timings; /* set_dv_bt_timings/get_dv_timings/query_dv_timings */
 static bool query_and_set_dv_timings = false;
 static int enum_and_set_dv_timings = -1;
-	
+
 void stds_usage(void)
 {
 	printf("\nStandards/Timings options:\n"
@@ -125,10 +125,70 @@ static v4l2_std_id parse_ntsc(const char *ntsc)
 	exit(1);
 }
 
+enum timing_opts {
+	WIDTH = 0,
+	HEIGHT,
+	INTERLACED,
+	POLARITIES,
+	PIXEL_CLOCK,
+	HORZ_FRONT_PORCH,
+	HORZ_SYNC,
+	HORZ_BACK_PORCH,
+	VERT_FRONT_PORCH,
+	VERT_SYNC,
+	VERT_BACK_PORCH,
+	IL_VERT_FRONT_PORCH,
+	IL_VERT_SYNC,
+	IL_VERT_BACK_PORCH,
+	INDEX,
+};
+
+static int parse_timing_subopt(char **subopt_str, int *value)
+{
+	int opt;
+	char *opt_str;
+
+	static const char * const subopt_list[] = {
+	[WIDTH] = "width",
+	[HEIGHT] = "height",
+	[INTERLACED] = "interlaced",
+	[POLARITIES] = "polarities",
+	[PIXEL_CLOCK] = "pixelclock",
+	[HORZ_FRONT_PORCH] = "hfp",
+	[HORZ_SYNC] = "hs",
+	[HORZ_BACK_PORCH] = "hbp",
+	[VERT_FRONT_PORCH] = "vfp",
+	[VERT_SYNC] = "vs",
+	[VERT_BACK_PORCH] = "vbp",
+	[IL_VERT_FRONT_PORCH] = "il_vfp",
+	[IL_VERT_SYNC] = "il_vs",
+	[IL_VERT_BACK_PORCH] = "il_vbp",
+	[INDEX] = "index",
+	NULL
+	};
+
+	opt = getsubopt(subopt_str, (char* const*) subopt_list, &opt_str);
+
+	if (opt == -1) {
+		fprintf(stderr, "Invalid suboptions specified\n");
+		stds_usage();
+		exit(1);
+	}
+	if (opt_str == NULL) {
+		fprintf(stderr, "No value given to suboption <%s>\n",
+				subopt_list[opt]);
+		stds_usage();
+		exit(1);
+	}
+
+	if (opt_str)
+		*value = strtol(opt_str, 0L, 0);
+	return opt;
+}
+
 static void parse_dv_bt_timings(char *optarg, struct v4l2_dv_timings *dv_timings,
 		bool &query, int &enumerate)
 {
-	char *value;
 	char *subs = optarg;
 	struct v4l2_bt_timings *bt = &dv_timings->bt;
 
@@ -140,70 +200,55 @@ static void parse_dv_bt_timings(char *optarg, struct v4l2_dv_timings *dv_timings
 	}
 
 	while (*subs != '\0') {
-		static const char *const subopts[] = {
-			"width",
-			"height",
-			"interlaced",
-			"polarities",
-			"pixelclock",
-			"hfp",
-			"hs",
-			"hbp",
-			"vfp",
-			"vs",
-			"vbp",
-			"il_vfp",
-			"il_vs",
-			"il_vbp",
-			"index",
-			NULL
-		};
-
-		switch (parse_subopt(&subs, subopts, &value)) {
-		case 0:
-			bt->width = atoi(value);
+		int opt;
+		int opt_val;
+
+		opt = parse_timing_subopt(&subs, &opt_val);
+		switch (opt) {
+		case WIDTH:
+			bt->width = opt_val;
 			break;
-		case 1:
-			bt->height = strtol(value, 0L, 0);
+		case HEIGHT:
+			bt->height = opt_val;
 			break;
-		case 2:
-			bt->interlaced = strtol(value, 0L, 0);
+		case INTERLACED:
+			bt->interlaced = opt_val;
 			break;
-		case 3:
-			bt->polarities = strtol(value, 0L, 0);
+		case POLARITIES:
+			bt->polarities = opt_val;
 			break;
-		case 4:
-			bt->pixelclock = strtol(value, 0L, 0);
+		case PIXEL_CLOCK:
+			bt->pixelclock = opt_val;
 			break;
-		case 5:
-			bt->hfrontporch = strtol(value, 0L, 0);
+		case HORZ_FRONT_PORCH:
+			bt->hfrontporch = opt_val;
 			break;
-		case 6:
-			bt->hsync = strtol(value, 0L, 0);
+		case HORZ_SYNC:
+			bt->hsync = opt_val;
 			break;
-		case 7:
-			bt->hbackporch = strtol(value, 0L, 0);
+		case HORZ_BACK_PORCH:
+			bt->hbackporch = opt_val;
 			break;
-		case 8:
-			bt->vfrontporch = strtol(value, 0L, 0);
+		case VERT_FRONT_PORCH:
+			bt->vfrontporch = opt_val;
 			break;
-		case 9:
-			bt->vsync = strtol(value, 0L, 0);
+		case VERT_SYNC:
+			bt->vsync = opt_val;
 			break;
-		case 10:
-			bt->vbackporch = strtol(value, 0L, 0);
+		case VERT_BACK_PORCH:
+			bt->vbackporch = opt_val;
 			break;
-		case 11:
-			bt->il_vfrontporch = strtol(value, 0L, 0);
+		case IL_VERT_FRONT_PORCH:
+			bt->il_vfrontporch = opt_val;
 			break;
-		case 12:
-			bt->il_vsync = strtol(value, 0L, 0);
+		case IL_VERT_SYNC:
+			bt->il_vsync = opt_val;
 			break;
-		case 13:
-			bt->il_vbackporch = strtol(value, 0L, 0);
+		case IL_VERT_BACK_PORCH:
+			bt->il_vbackporch = opt_val;
 			break;
-		case 14:
-			enumerate = strtol(value, 0L, 0);
+		case INDEX:
+			enumerate = opt_val;
 			break;
 		default:
 			stds_usage();
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] v4l2-ctl-stds: Support cvt/gtf options in set-dv-bt-timings
  2015-03-20  6:33 Support for CVT, GTF timings Prashant Laddha
  2015-03-20  6:33 ` [PATCH 1/3] v4l2-ctl: Add support for CVT, GTF modeline calculation Prashant Laddha
  2015-03-20  6:33 ` [PATCH 2/3] v4l2-ctl-stds: Restructured suboption parsing code Prashant Laddha
@ 2015-03-20  6:33 ` Prashant Laddha
  2 siblings, 0 replies; 7+ messages in thread
From: Prashant Laddha @ 2015-03-20  6:33 UTC (permalink / raw)
  To: Linux Media Mailing List; +Cc: Hans Verkuil, Prashant Laddha

Added support to parse cvt/gtf suboptions- width, height, refresh
rate, reduced blanking, interlaced.

The cvt/gtf modeline calculations are implemented v4l2-ctl-modes.cpp.
Calling those APIs to update v4l2_bt_timings structure.

Cc: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Prashant Laddha <prladdha@cisco.com>
---
 utils/v4l2-ctl/v4l2-ctl-stds.cpp | 82 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 80 insertions(+), 2 deletions(-)

diff --git a/utils/v4l2-ctl/v4l2-ctl-stds.cpp b/utils/v4l2-ctl/v4l2-ctl-stds.cpp
index 2141876..0e4f810 100644
--- a/utils/v4l2-ctl/v4l2-ctl-stds.cpp
+++ b/utils/v4l2-ctl/v4l2-ctl-stds.cpp
@@ -39,6 +39,9 @@ void stds_usage(void)
 	       "  --set-dv-bt-timings\n"
 	       "                     query: use the output of VIDIOC_QUERY_DV_TIMINGS\n"
 	       "                     index=<index>: use the index as provided by --list-dv-timings\n"
+	       "                     or specify timings using cvt/gtf options as follows:\n"
+	       "                     cvt/gtf,width=<width>,height=<height>,fps=<frames per sec>\n"
+	       "                     interlaced=<0/1>,reduced-blanking=<0/1>\n"
 	       "                     or give a fully specified timings:\n"
 	       "                     width=<width>,height=<height>,interlaced=<0/1>,\n"
 	       "                     polarities=<polarities mask>,pixelclock=<pixelclock Hz>,\n"
@@ -141,6 +144,10 @@ enum timing_opts {
 	IL_VERT_SYNC,
 	IL_VERT_BACK_PORCH,
 	INDEX,
+	CVT,
+	GTF,
+	FPS,
+	REDUCED_BLANK,
 };
 
 static int parse_timing_subopt(char **subopt_str, int *value)
@@ -164,6 +171,10 @@ static int parse_timing_subopt(char **subopt_str, int *value)
 	[IL_VERT_SYNC] = "il_vs",
 	[IL_VERT_BACK_PORCH] = "il_vbp",
 	[INDEX] = "index",
+	[CVT] = "cvt",
+	[GTF] = "gtf",
+	[FPS] = "fps",
+	[REDUCED_BLANK] = "reduced-blanking",
 	NULL
 	};
 
@@ -174,7 +185,7 @@ static int parse_timing_subopt(char **subopt_str, int *value)
 		stds_usage();
 		exit(1);
 	}
-	if (opt_str == NULL) {
+	if (opt_str == NULL && opt != CVT && opt != GTF) {
 		fprintf(stderr, "No value given to suboption <%s>\n",
 				subopt_list[opt]);
 		stds_usage();
@@ -186,11 +197,69 @@ static int parse_timing_subopt(char **subopt_str, int *value)
 	return opt;
 }
 
+static void get_cvt_gtf_timings(char *subopt, int standard,
+				struct v4l2_bt_timings *bt)
+{
+	int width = 0;
+	int height = 0;
+	int fps = 0;
+	int r_blank = 0;
+	int interlaced = 0;
+
+	bool timings_valid = false;
+
+	char *subopt_str = subopt;
+	while (*subopt_str != '\0') {
+		int opt;
+		int opt_val;
+
+		opt = parse_timing_subopt(&subopt_str, &opt_val);
+
+		switch (opt) {
+		case WIDTH:
+			width = opt_val;
+			break;
+		case HEIGHT:
+			height = opt_val;
+			break;
+		case FPS:
+			fps = opt_val;
+			break;
+		case REDUCED_BLANK:
+			r_blank = opt_val;
+			break;
+		case INTERLACED:
+			interlaced = opt_val;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (standard == V4L2_DV_BT_STD_CVT) {
+		timings_valid = calc_cvt_modeline(width, height, fps,
+			              r_blank == 1 ? true : false,
+			              interlaced == 1 ? true : false,
+			              bt);
+	} else {
+		timings_valid = calc_gtf_modeline(width, height, fps,
+			              r_blank == 1 ? true : false,
+			              interlaced == 1 ? true : false,
+			              bt);
+	}
+
+	if (!timings_valid) {
+		stds_usage();
+		exit(1);
+	}
+}
+
 static void parse_dv_bt_timings(char *optarg, struct v4l2_dv_timings *dv_timings,
 		bool &query, int &enumerate)
 {
 	char *subs = optarg;
 	struct v4l2_bt_timings *bt = &dv_timings->bt;
+	bool parse_cvt_gtf = false;
 
 	dv_timings->type = V4L2_DV_BT_656_1120;
 
@@ -199,11 +268,12 @@ static void parse_dv_bt_timings(char *optarg, struct v4l2_dv_timings *dv_timings
 		return;
 	}
 
-	while (*subs != '\0') {
+	while (*subs != '\0' && !parse_cvt_gtf) {
 		int opt;
 		int opt_val;
 
 		opt = parse_timing_subopt(&subs, &opt_val);
+
 		switch (opt) {
 		case WIDTH:
 			bt->width = opt_val;
@@ -250,6 +320,14 @@ static void parse_dv_bt_timings(char *optarg, struct v4l2_dv_timings *dv_timings
 		case INDEX:
 			enumerate = opt_val;
 			break;
+		case CVT:
+			parse_cvt_gtf = true;
+			get_cvt_gtf_timings(subs, V4L2_DV_BT_STD_CVT, bt);
+			break;
+		case GTF:
+			parse_cvt_gtf = true;
+			get_cvt_gtf_timings(subs, V4L2_DV_BT_STD_GTF, bt);
+			break;
 		default:
 			stds_usage();
 			exit(1);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] v4l2-ctl: Add support for CVT, GTF modeline calculation
  2015-03-20  6:33 ` [PATCH 1/3] v4l2-ctl: Add support for CVT, GTF modeline calculation Prashant Laddha
@ 2015-03-20 11:30   ` Hans Verkuil
  2015-03-20 14:19     ` Prashant Laddha (prladdha)
  0 siblings, 1 reply; 7+ messages in thread
From: Hans Verkuil @ 2015-03-20 11:30 UTC (permalink / raw)
  To: Prashant Laddha, Linux Media Mailing List; +Cc: Hans Verkuil

Hi Prashant,

Thanks for the patch, but I have one small comment:

On 03/20/2015 07:33 AM, Prashant Laddha wrote:
> This patch adds support for calculating v4l2_bt_timings based on
> CVT and GTF standards. The timings are calculated for a given
> standard, CVT or GTF using a set of parameters- width, height,
> refresh rate and flags like whether it is an interlaced format,
> and whether to use reduced blanking.
> 
> CVT Modeline calculation -
> Implements Coordinated Video Timings (CVT) Standard Ver 1.2 Feb 08,
> 2013. The timing calculations are based on VESA CVT Generator Rev 1.2
> by Graham Loveridge May 28, 2013.
> 
> GTF modeline calculation -
> Implements Generalized Timing Formula (GTF) Standard Ver 1.1 Sept 02,
> 1999. The timing calculations are based on GTF timing spreadsheet by
> Andy Morrish. The default GTF timings are used if flag for reduced
> blanking is false, otherwise secondary GTF timings are used.
> 
> Suggested by: Hans Verkuil <hans.verkuil@cisco.com>
> 
> Cc: Hans Verkuil <hans.verkuil@cisco.com>
> Signed-off-by: Prashant Laddha <prladdha@cisco.com>
> ---
>  utils/v4l2-ctl/Makefile.am        |   3 +-
>  utils/v4l2-ctl/v4l2-ctl-modes.cpp | 512 ++++++++++++++++++++++++++++++++++++++
>  utils/v4l2-ctl/v4l2-ctl.h         |   8 +
>  3 files changed, 522 insertions(+), 1 deletion(-)
>  create mode 100644 utils/v4l2-ctl/v4l2-ctl-modes.cpp
> 

> diff --git a/utils/v4l2-ctl/v4l2-ctl-modes.cpp b/utils/v4l2-ctl/v4l2-ctl-modes.cpp
> new file mode 100644
> index 0000000..5157fea
> --- /dev/null
> +++ b/utils/v4l2-ctl/v4l2-ctl-modes.cpp

<snip>

> +	if (cvt->interlaced == V4L2_DV_INTERLACED) {
> +		cvt->il_vfrontporch = v_fp;
> +		cvt->il_vsync = v_sync;
> +		cvt->il_vbackporch = v_bp;
> +		/* For interlaced format, add half lines to front and back
> +		 * porches of odd and even fields respectively */
> +		cvt->flags |= V4L2_DV_FL_HALF_LINE;
> +		cvt->vfrontporch += 1;
> +		cvt->il_vbackporch += 1;

This isn't right, you should do the +1 only for the il_vbackporch. Otherwise
V4L2_DV_BT_FRAME_HEIGHT(bt) would be one too big.

The HALF_LINE flag means that, if drivers support it, they can add a half-line
to the vfrontporch of the odd field and subtract a half-line for the vbackporch
of the even field.

BTW, the V4L2_DV_FL_HALF_LINE documentation in the spec should be improved to
state the above. Right now it doesn't specify to which porch the half-lines go.

This same bug is in the detect_gtf function.

Regards,

	Hans

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] v4l2-ctl: Add support for CVT, GTF modeline calculation
       [not found] <[PATCH 1/3] v4l2-ctl: Add support for CVT, GTF modeline calculation>
@ 2015-03-20 14:12 ` Prashant Laddha
  0 siblings, 0 replies; 7+ messages in thread
From: Prashant Laddha @ 2015-03-20 14:12 UTC (permalink / raw)
  To: Linux Media Mailing List; +Cc: Hans Verkuil, Prashant Laddha

This patch adds support for calculating v4l2_bt_timings based on
CVT and GTF standards. The timings are calculated for a given
standard, CVT or GTF using a set of parameters- width, height,
refresh rate and flags like whether it is an interlaced format,
and whether to use reduced blanking.

CVT Modeline calculation -
Implements Coordinated Video Timings (CVT) Standard Ver 1.2 Feb 08,
2013. The timing calculations are based on VESA CVT Generator Rev 1.2
by Graham Loveridge May 28, 2013.

GTF modeline calculation -
Implements Generalized Timing Formula (GTF) Standard Ver 1.1 Sept 02,
1999. The timing calculations are based on GTF timing spreadsheet by
Andy Morrish. The default GTF timings are used if flag for reduced
blanking is false, otherwise secondary GTF timings are used.

Suggested by: Hans Verkuil <hans.verkuil@cisco.com>

Cc: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Prashant Laddha <prladdha@cisco.com>
---
 utils/v4l2-ctl/Makefile.am        |   3 +-
 utils/v4l2-ctl/v4l2-ctl-modes.cpp | 518 ++++++++++++++++++++++++++++++++++++++
 utils/v4l2-ctl/v4l2-ctl.h         |   8 +
 3 files changed, 528 insertions(+), 1 deletion(-)
 create mode 100644 utils/v4l2-ctl/v4l2-ctl-modes.cpp

diff --git a/utils/v4l2-ctl/Makefile.am b/utils/v4l2-ctl/Makefile.am
index 29dd6cb..bc3f746 100644
--- a/utils/v4l2-ctl/Makefile.am
+++ b/utils/v4l2-ctl/Makefile.am
@@ -9,7 +9,8 @@ ivtv_ctl_LDFLAGS = -lm
 v4l2_ctl_SOURCES = v4l2-ctl.cpp v4l2-ctl.h v4l2-ctl-common.cpp v4l2-ctl-tuner.cpp \
 	v4l2-ctl-io.cpp v4l2-ctl-stds.cpp v4l2-ctl-vidcap.cpp v4l2-ctl-vidout.cpp \
 	v4l2-ctl-overlay.cpp v4l2-ctl-vbi.cpp v4l2-ctl-selection.cpp v4l2-ctl-misc.cpp \
-	v4l2-ctl-streaming.cpp v4l2-ctl-sdr.cpp v4l2-ctl-edid.cpp vivid-tpg-colors.c vivid-tpg.c
+	v4l2-ctl-streaming.cpp v4l2-ctl-sdr.cpp v4l2-ctl-edid.cpp v4l2-ctl-modes.cpp \
+	vivid-tpg-colors.c vivid-tpg.c
 v4l2_ctl_LDADD = ../../lib/libv4l2/libv4l2.la ../../lib/libv4lconvert/libv4lconvert.la
 v4l2_ctl_LDFLAGS = -lrt
 
diff --git a/utils/v4l2-ctl/v4l2-ctl-modes.cpp b/utils/v4l2-ctl/v4l2-ctl-modes.cpp
new file mode 100644
index 0000000..f8a3aea
--- /dev/null
+++ b/utils/v4l2-ctl/v4l2-ctl-modes.cpp
@@ -0,0 +1,518 @@
+/*
+ * v4l2-ctl-modes.cpp - functions to calculate cvt and gtf mode timings.
+ *
+ * Copyright 2015 Cisco Systems, Inc. and/or its affiliates. All rights
+ * reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include "v4l2-ctl.h"
+
+static bool valid_params(int width, int height, int refresh_rate)
+{
+	if (width <= 0) {
+		fprintf(stderr, "Invalid value %d for width\n", width);
+		return false;
+	}
+
+	if (height <= 0) {
+		fprintf(stderr, "Invalid value %d for height\n", height);
+		return false;
+	}
+
+	if (refresh_rate <= 0) {
+		fprintf(stderr, "Invalid value %d for refresh rate\n",
+				refresh_rate);
+		return false;
+	}
+	return true;
+}
+
+#define HV_FACTOR		(1000)
+#define CVT_MARGIN_PERCENT	  (18)
+#define CVT_HSYNC_PERCENT	   (8)
+
+/*
+ * CVT defines Based on
+ * Coordinated Video Timings Standard Ver 1.2 Feb 08, 2013
+ */
+
+#define CVT_PXL_CLK_GRAN    (250000)  /* pixel clock granularity */
+
+/* Normal blanking */
+#define CVT_MIN_V_BPORCH     (7)  /* lines */
+#define CVT_MIN_V_PORCH_RND  (3)  /* lines */
+#define CVT_MIN_VSYNC_BP    (550) /* time v_sync + back porch (us)*/
+
+/* Normal blanking for CVT uses GTF
+ * to calculate horizontal blanking */
+#define CVT_CELL_GRAN	(8)	  /* character cell granularity */
+#define CVT_M	      (600)	  /* blanking formula gradient */
+#define CVT_C	       (40)	  /* blanking formula offset */
+#define CVT_K	      (128)	  /* blanking formula scale factor */
+#define CVT_J	       (20)	  /* blanking formula scale factor */
+
+#define CVT_C_PRIME (((CVT_C - CVT_J) * CVT_K / 256) + CVT_J)
+#define CVT_M_PRIME (CVT_K * CVT_M / 256)
+
+/* Reduced Blanking */
+#define CVT_RB_MIN_V_BPORCH    (7)       /* lines  */
+#define CVT_RB_V_FPORCH        (3)       /* lines  */
+#define CVT_RB_MIN_V_BLANK   (460)       /* us     */
+#define CVT_RB_H_SYNC         (32)       /* pixels */
+#define CVT_RB_H_BPORCH       (80)       /* pixels */
+#define CVT_RB_H_BLANK       (160)       /* pixels */
+
+static int v_sync_from_aspect_ratio(int width, int height)
+{
+	if (((height * 4 / 3) / CVT_CELL_GRAN) * CVT_CELL_GRAN == width)
+		return 4;
+
+	if (((height * 16 / 9) / CVT_CELL_GRAN) * CVT_CELL_GRAN == width)
+		return 5;
+
+	if (((height * 16 / 10) / CVT_CELL_GRAN) * CVT_CELL_GRAN == width)
+		return 6;
+
+	if (((height * 5 / 4) / CVT_CELL_GRAN) * CVT_CELL_GRAN == width)
+		return 7;
+
+	if (((height * 15 / 9) / CVT_CELL_GRAN) * CVT_CELL_GRAN == width)
+		return 7;
+
+	/* custom aspect ratio */
+	fprintf(stderr, "Warning!  Aspect ratio is not CVT Standard\n");
+	return 10;
+}
+
+/**
+ * calc_cvt_modeline - calculate modeline based on CVT algorithm
+ *
+ * This function is called to generate the timings according to CVT
+ * algorithm. Timing calculation is based on VESA(TM) Coordinated
+ * Video Timing Generator Rev 1.2 by  Graham Loveridge May 28, 2013
+ * which can be downloaded from -
+ * http://www.vesa.org/vesa-standards/free-standards/
+ *
+ * Input Parameters:
+ * @image_width
+ * @image_height
+ * @refresh_rate
+ * @reduced_blanking: whether to use reduced blanking
+ * @interlaced: whether to compute an interlaced mode
+ * @cvt: stores results of cvt timing calculation
+ *
+ * Returns:
+ * true, if cvt timings are calculated and filled in cvt modeline.
+ * false, for any error
+ */
+
+bool calc_cvt_modeline(int image_width, int image_height,
+		       int refresh_rate, bool reduced_blanking,
+		       bool interlaced, struct v4l2_bt_timings *cvt)
+{
+	int h_sync;
+	int v_sync;
+	int h_fp;
+	int h_bp;
+	int v_fp;
+	int v_bp;
+
+	int h_pixel;
+	int v_lines;
+	int h_pixel_rnd;
+	int v_lines_rnd;
+	int active_h_pixel;
+	int active_v_lines;
+	int total_h_pixel;
+	int total_v_lines;
+
+	int h_blank;
+	int v_blank;
+
+	int h_period;
+
+	int interlace;
+	int v_refresh;
+	int pixel_clock;
+
+	if (!valid_params(image_width, image_height, refresh_rate))
+		return false;
+
+	h_pixel = image_width;
+	v_lines = image_height;
+
+	if (!refresh_rate)
+		v_refresh = 60;
+	else
+		v_refresh = refresh_rate;
+
+	if (v_refresh != 50 && v_refresh != 60 &&
+		v_refresh != 75 && v_refresh != 85)
+		fprintf(stderr, "Warning!  Refresh rate is not CVT standard\n");
+
+	if (interlaced) {
+		interlace = 1;
+		v_lines_rnd = v_lines / 2;
+		v_refresh = v_refresh * 2;
+
+		if ((v_lines_rnd * 2) != v_lines)
+			fprintf(stderr,
+			"Warning!  Vertical lines rounded to nearest integer\n");
+	} else {
+		interlace = 0;
+		v_lines_rnd = v_lines;
+	}
+
+	h_pixel_rnd = h_pixel - (h_pixel % CVT_CELL_GRAN);
+
+	if (h_pixel_rnd != h_pixel)
+		fprintf(stderr,
+		"Warning!  Horizontal pixels rounded to nearest character cell\n");
+
+	active_h_pixel = h_pixel_rnd;
+	active_v_lines = v_lines_rnd;
+
+	v_sync = v_sync_from_aspect_ratio(h_pixel, v_lines);
+
+	if (!reduced_blanking) {
+		int tmp1, tmp2;
+		int ideal_blank_duty_cycle;
+		int v_sync_bp;
+
+		/* estimate the horizontal period */
+		tmp1 = HV_FACTOR * 1000000  -
+			   CVT_MIN_VSYNC_BP * HV_FACTOR * v_refresh;
+		tmp2 = (active_v_lines + CVT_MIN_V_PORCH_RND) * 2 + interlace;
+
+		h_period = tmp1 * 2 / (tmp2 * v_refresh);
+
+		tmp1 = CVT_MIN_VSYNC_BP * HV_FACTOR / h_period + 1;
+
+		if (tmp1 < (v_sync + CVT_MIN_V_PORCH_RND))
+			v_sync_bp = v_sync + CVT_MIN_V_PORCH_RND;
+		else
+			v_sync_bp = tmp1;
+
+		v_bp = v_sync_bp - v_sync;
+		v_fp = CVT_MIN_V_PORCH_RND;
+
+		ideal_blank_duty_cycle = (CVT_C_PRIME * HV_FACTOR) -
+					  CVT_M_PRIME * h_period / 1000;
+
+		if (ideal_blank_duty_cycle < 20 * HV_FACTOR)
+			ideal_blank_duty_cycle = 20 * HV_FACTOR;
+
+		h_blank = active_h_pixel * ideal_blank_duty_cycle /
+			 (100 * HV_FACTOR - ideal_blank_duty_cycle);
+		h_blank -= h_blank % (2 * CVT_CELL_GRAN);
+
+		v_blank = v_sync_bp + CVT_MIN_V_PORCH_RND;
+
+		total_v_lines = active_v_lines + v_blank + interlace;
+		total_h_pixel = active_h_pixel + h_blank;
+
+		h_sync  = (total_h_pixel * CVT_HSYNC_PERCENT) / 100;
+		h_sync -= h_sync % CVT_CELL_GRAN;
+
+		h_bp = h_blank / 2;
+		h_fp = h_blank - h_bp - h_sync;
+
+	} else {
+		/* Reduced blanking */
+
+		int vbi_lines;
+		int tmp1, tmp2;
+
+		/* estimate horizontal period. */
+		tmp1 = HV_FACTOR * 1000000 -
+			   CVT_RB_MIN_V_BLANK * HV_FACTOR * v_refresh;
+		tmp2 = active_v_lines;
+
+		h_period = tmp1 / (tmp2 * v_refresh);
+
+		vbi_lines = CVT_RB_MIN_V_BLANK * HV_FACTOR / h_period + 1;
+
+		if (vbi_lines < (CVT_RB_V_FPORCH + v_sync + CVT_MIN_V_BPORCH))
+			vbi_lines = CVT_RB_V_FPORCH + v_sync + CVT_MIN_V_BPORCH;
+
+		total_v_lines = active_v_lines + vbi_lines;
+
+		total_h_pixel = active_h_pixel + CVT_RB_H_BLANK;
+
+		h_blank = CVT_RB_H_BLANK;
+		v_blank = vbi_lines;
+
+		h_sync = CVT_RB_H_SYNC;
+
+		h_bp = h_blank / 2;
+		h_fp = h_blank - h_bp - h_sync;
+
+		v_fp = CVT_RB_V_FPORCH;
+		v_bp = v_blank - v_fp - v_sync;
+	}
+
+	pixel_clock =  ((long long)total_h_pixel * HV_FACTOR * 1000000)
+			/ h_period;
+	pixel_clock -= pixel_clock  % CVT_PXL_CLK_GRAN;
+
+	cvt->standards 	 = V4L2_DV_BT_STD_CVT;
+
+	cvt->width       = h_pixel;
+	cvt->hfrontporch = h_fp;
+	cvt->hsync       = h_sync;
+	cvt->hbackporch  = h_bp;
+
+	cvt->height      = v_lines;
+	cvt->vfrontporch = v_fp;
+	cvt->vsync       = v_sync;
+	cvt->vbackporch  = v_bp;
+
+	cvt->pixelclock = pixel_clock;
+	cvt->interlaced = interlaced == 1 ?
+			V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
+
+	if (cvt->interlaced == V4L2_DV_INTERLACED) {
+		cvt->il_vfrontporch = v_fp;
+		cvt->il_vsync = v_sync;
+		cvt->il_vbackporch = v_bp;
+		/* Add 1 to vbackporch of even field and set the half line
+		 * flag (V4L2_DV_FL_HALF_LINE)
+		 * For interlaced format, the half line flag indicates to the
+		 * driver to add a half-line to the vfrontporch of the odd
+		 * field and subtract a half-line from the vbackporch of the
+		 * even field */
+		cvt->flags |= V4L2_DV_FL_HALF_LINE;
+		cvt->il_vbackporch += 1;
+	}
+	if (reduced_blanking) {
+		cvt->polarities = V4L2_DV_HSYNC_POS_POL;
+		cvt->flags |= V4L2_DV_FL_REDUCED_BLANKING;
+	} else
+		cvt->polarities = V4L2_DV_VSYNC_POS_POL;
+
+	return true;
+}
+
+
+/*
+ * GTF defines Based on Generalized Timing Formula Standard
+ * Version 1.1 September 2, 1999
+ */
+
+#define GTF_MARGIN_PERCENT	  (18)
+#define GTF_HSYNC_PERCENT	   (8)
+
+#define GTF_PXL_CLK_GRAN (250000) /* pixel clock granularity */
+
+#define GTF_V_SYNC_RQD	   (3) /* v sync required (lines) */
+#define GTF_MIN_VSYNC_BP (550) /* min time vsync + back porch (us) */
+#define GTF_MIN_PORCH	   (1) /* vertical front porch (lines) */
+#define GTF_CELL_GRAN      (8) /* character cell granularity */
+
+/* Default */
+#define GTF_D_M		(600)	 /* blanking formula gradient */
+#define GTF_D_C		 (40)    /* blanking formula offset */
+#define GTF_D_K		(128)	 /* blanking formula scaling factor */
+#define GTF_D_J		 (20)	 /* blanking formula scaling factor */
+#define GTF_D_C_PRIME ((((GTF_D_C - GTF_D_J) * GTF_D_K) / 256) + GTF_D_J)
+#define GTF_D_M_PRIME ((GTF_D_K * GTF_D_M) / 256)
+
+/* Secondary */
+#define GTF_S_M		 (3600)	    /* blanking formula gradient */
+#define GTF_S_C		   (40)	    /* blanking formula offset */
+#define GTF_S_K		  (128)	    /* blanking formula scaling factor */
+#define GTF_S_J		   (35)	    /* blanking formula scaling factor */
+#define GTF_S_C_PRIME ((((GTF_S_C - GTF_S_J) * GTF_S_K) / 256) + GTF_S_J)
+#define GTF_S_M_PRIME ((GTF_S_K * GTF_S_M) / 256)
+
+/**
+ * calc_gtf_modeline - calculate modeline based on GTF algorithm
+ *
+ * This function is called to generate the timings according to GTF
+ * algorithm. Timing calculation is based on VESA(TM) Generalized
+ * Timing Formula Standard Version 1.1 September 2, 1999
+ * which can be downloaded from -
+ * http://www.vesa.org/vesa-standards/free-standards/
+ *
+ * Input Parameters:
+ * @image_width
+ * @image_height
+ * @refresh_rate
+ * @reduced_blanking: whether to use reduced blanking
+ * @interlaced: whether to compute an interlaced mode
+ * @gtf: stores results of gtf timing calculation
+ *
+ * Returns:
+ * true, if gtf timings are calculated and filled in gtf modeline.
+ * false, for any error.
+ */
+
+bool calc_gtf_modeline(int image_width, int image_height,
+		       int refresh_rate, bool reduced_blanking,
+		       bool interlaced, struct v4l2_bt_timings *gtf)
+{
+	int h_sync;
+	int v_sync;
+	int h_fp;
+	int h_bp;
+	int v_fp;
+	int v_bp;
+
+	int h_pixel;
+	int v_lines;
+	int h_pixel_rnd;
+	int v_lines_rnd;
+	int active_h_pixel;
+	int active_v_lines;
+	int total_h_pixel;
+	int total_v_lines;
+
+	int h_blank;
+	int v_blank;
+
+	int h_period;
+	int h_period_est;
+
+	int interlace;
+	int v_refresh;
+	int v_refresh_est;
+	int pixel_clock;
+
+	int v_sync_bp;
+	int tmp1, tmp2;
+	int ideal_blank_duty_cycle;
+
+	if (!gtf) {
+		fprintf(stderr, "Null pointer to gtf modeline structure\n");
+		return false;
+	}
+
+	if (!valid_params(image_width, image_height, refresh_rate))
+		return false;
+
+	h_pixel = image_width;
+	v_lines = image_height;
+
+	if (!refresh_rate)
+		v_refresh = 60;
+	else
+		v_refresh = refresh_rate;
+
+	if (interlaced) {
+		interlace = 1;
+		v_lines_rnd = v_lines / 2;
+		v_refresh = v_refresh * 2;
+	} else {
+		interlace = 0;
+		v_lines_rnd = v_lines;
+	}
+
+	h_pixel_rnd = (h_pixel + GTF_CELL_GRAN / 2);
+	h_pixel_rnd -= h_pixel_rnd % GTF_CELL_GRAN;
+
+	active_h_pixel = h_pixel_rnd;
+	active_v_lines = v_lines_rnd;
+
+		/* estimate the horizontal period */
+	tmp1 = HV_FACTOR * 1000000  -
+		   GTF_MIN_VSYNC_BP * HV_FACTOR * v_refresh;
+	tmp2 = active_v_lines + GTF_MIN_PORCH + interlace;
+
+	h_period_est = tmp1 / (tmp2 * v_refresh);
+
+	v_sync_bp = GTF_MIN_VSYNC_BP * HV_FACTOR * 100 / h_period_est;
+	v_sync_bp = (v_sync_bp + 50) / 100;
+
+	v_sync = GTF_V_SYNC_RQD;
+	v_bp = v_sync_bp - v_sync;
+	v_fp = GTF_MIN_PORCH;
+
+	v_blank = v_sync + v_bp + v_fp;
+	total_v_lines = active_v_lines + v_blank + interlace;
+
+	v_refresh_est = (HV_FACTOR * (long long)1000000) /
+			(h_period_est * total_v_lines / HV_FACTOR);
+
+	h_period = (h_period_est * v_refresh_est) /
+		   (v_refresh * HV_FACTOR);
+
+	if (!reduced_blanking)
+		ideal_blank_duty_cycle = (GTF_D_C_PRIME * HV_FACTOR) -
+				      GTF_D_M_PRIME * h_period / 1000;
+	else
+		ideal_blank_duty_cycle = (GTF_S_C_PRIME * HV_FACTOR) -
+				      GTF_S_M_PRIME * h_period / 1000;
+
+
+	h_blank = active_h_pixel * ideal_blank_duty_cycle /
+			 (100 * HV_FACTOR - ideal_blank_duty_cycle);
+	h_blank -= h_blank % (2 * GTF_CELL_GRAN);
+
+	total_h_pixel = active_h_pixel + h_blank;
+
+	h_sync  = (total_h_pixel * GTF_HSYNC_PERCENT) / 100;
+	h_sync -= h_sync % GTF_CELL_GRAN;
+
+	h_fp = h_blank / 2 - h_sync;
+	h_bp = h_fp + h_sync;
+
+	pixel_clock = ((long long)total_h_pixel * HV_FACTOR * 1000000)
+					/ h_period;
+	/* Not sure if clock value needs to be truncated to multiple
+	 * of 25000. The formula given in standard does not indicate
+	 * truncation
+	 * */
+	/*pixel_clock -= pixel_clock  % GTF_PXL_CLK_GRAN;*/
+
+	gtf->standards 	 = V4L2_DV_BT_STD_GTF;
+
+	gtf->width       = h_pixel;
+	gtf->hfrontporch = h_fp;
+	gtf->hsync       = h_sync;
+	gtf->hbackporch  = h_bp;
+
+	gtf->height      = v_lines;
+	gtf->vfrontporch = v_fp;
+	gtf->vsync       = v_sync;
+	gtf->vbackporch  = v_bp;
+
+	gtf->pixelclock = pixel_clock;
+	gtf->interlaced = interlaced == 1 ?
+			V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
+
+	if (gtf->interlaced == V4L2_DV_INTERLACED) {
+		gtf->il_vfrontporch = v_fp;
+		gtf->il_vsync = v_sync;
+		gtf->il_vbackporch = v_bp;
+		/* Add 1 to vbackporch of even field and set the half line
+		 * flag (V4L2_DV_FL_HALF_LINE)
+		 * For interlaced format, the half line flag indicates to the
+		 * driver to add a half-line to the vfrontporch of the odd
+		 * field and subtract a half-line from the vbackporch of the
+		 * even field */
+		gtf->flags |= V4L2_DV_FL_HALF_LINE;
+		gtf->il_vbackporch += 1;
+	}
+	if (reduced_blanking) {
+		gtf->polarities = V4L2_DV_HSYNC_POS_POL;
+		gtf->flags |= V4L2_DV_FL_REDUCED_BLANKING;
+	} else
+		gtf->polarities = V4L2_DV_VSYNC_POS_POL;
+
+	return true;
+}
diff --git a/utils/v4l2-ctl/v4l2-ctl.h b/utils/v4l2-ctl/v4l2-ctl.h
index f8b3df2..e47612f 100644
--- a/utils/v4l2-ctl/v4l2-ctl.h
+++ b/utils/v4l2-ctl/v4l2-ctl.h
@@ -347,4 +347,12 @@ void edid_cmd(int ch, char *optarg);
 void edid_set(int fd);
 void edid_get(int fd);
 
+/* v4l2-ctl-modes.cpp */
+bool calc_cvt_modeline(int image_width, int image_height,
+		       int refresh_rate, bool reduced_blanking,
+		       bool interlaced, struct v4l2_bt_timings *cvt);
+
+bool calc_gtf_modeline(int image_width, int image_height,
+		       int refresh_rate, bool reduced_blanking,
+		       bool interlaced, struct v4l2_bt_timings *gtf);
 #endif
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] v4l2-ctl: Add support for CVT, GTF modeline calculation
  2015-03-20 11:30   ` Hans Verkuil
@ 2015-03-20 14:19     ` Prashant Laddha (prladdha)
  0 siblings, 0 replies; 7+ messages in thread
From: Prashant Laddha (prladdha) @ 2015-03-20 14:19 UTC (permalink / raw)
  To: Hans Verkuil, Linux Media Mailing List; +Cc: Hans Verkuil

Hello Hans,

Thanks for reviewing the patch.

On 20/03/15 5:00 pm, "Hans Verkuil" <hverkuil@xs4all.nl> wrote:
>
>> +	if (cvt->interlaced == V4L2_DV_INTERLACED) {
>> +		cvt->il_vfrontporch = v_fp;
>> +		cvt->il_vsync = v_sync;
>> +		cvt->il_vbackporch = v_bp;
>> +		/* For interlaced format, add half lines to front and back
>> +		 * porches of odd and even fields respectively */
>> +		cvt->flags |= V4L2_DV_FL_HALF_LINE;
>> +		cvt->vfrontporch += 1;
>> +		cvt->il_vbackporch += 1;
>
>This isn't right, you should do the +1 only for the il_vbackporch.
>Otherwise
>V4L2_DV_BT_FRAME_HEIGHT(bt) would be one too big.
>
>The HALF_LINE flag means that, if drivers support it, they can add a
>half-line
>to the vfrontporch of the odd field and subtract a half-line for the
>vbackporch
>of the even field.
>
>BTW, the V4L2_DV_FL_HALF_LINE documentation in the spec should be
>improved to
>state the above. Right now it doesn't specify to which porch the
>half-lines go.
>
>This same bug is in the detect_gtf function.

Will fix this bug and resubmit the patch.

Regards,
Prashany
>


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-03-20 14:28 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-03-20  6:33 Support for CVT, GTF timings Prashant Laddha
2015-03-20  6:33 ` [PATCH 1/3] v4l2-ctl: Add support for CVT, GTF modeline calculation Prashant Laddha
2015-03-20 11:30   ` Hans Verkuil
2015-03-20 14:19     ` Prashant Laddha (prladdha)
2015-03-20  6:33 ` [PATCH 2/3] v4l2-ctl-stds: Restructured suboption parsing code Prashant Laddha
2015-03-20  6:33 ` [PATCH 3/3] v4l2-ctl-stds: Support cvt/gtf options in set-dv-bt-timings Prashant Laddha
     [not found] <[PATCH 1/3] v4l2-ctl: Add support for CVT, GTF modeline calculation>
2015-03-20 14:12 ` [PATCH 1/3] v4l2-ctl: Add support for CVT, GTF modeline calculation Prashant Laddha

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).