Re: [PATCH v5 06/22] drm/modes: Add a function to generate analog display modes

2022-10-18 Thread Maxime Ripard
Hi,

On Sun, Oct 16, 2022 at 07:34:12PM +0200, Mateusz Kwiatkowski wrote:
> Hi Maxime & everyone,
> 
> Sorry for being inactive in the discussions about this patchset for the last
> couple of weeks.
> 
> > +const static struct analog_parameters tv_modes_parameters[] = {
> > +   TV_MODE_PARAMETER(DRM_MODE_ANALOG_NTSC,
> > + NTSC_LINES_NUMBER,
> > + NTSC_LINE_DURATION_NS,
> > + PARAM_RANGE(NTSC_HACT_DURATION_MIN_NS,
> > + NTSC_HACT_DURATION_TYP_NS,
> > + NTSC_HACT_DURATION_MAX_NS),
> > + PARAM_RANGE(NTSC_HFP_DURATION_MIN_NS,
> > + NTSC_HFP_DURATION_TYP_NS,
> > + NTSC_HFP_DURATION_MAX_NS),
> > + PARAM_RANGE(NTSC_HSLEN_DURATION_MIN_NS,
> > + NTSC_HSLEN_DURATION_TYP_NS,
> > + NTSC_HSLEN_DURATION_MAX_NS),
> > + PARAM_RANGE(NTSC_HBP_DURATION_MIN_NS,
> > + NTSC_HBP_DURATION_TYP_NS,
> > + NTSC_HBP_DURATION_MAX_NS),
> > + PARAM_RANGE(NTSC_HBLK_DURATION_MIN_NS,
> > + NTSC_HBLK_DURATION_TYP_NS,
> > + NTSC_HBLK_DURATION_MAX_NS),
> > + 16,
> > + PARAM_FIELD(3, 3),
> > + PARAM_FIELD(3, 3),
> > + PARAM_FIELD(16, 17)),
> > +   TV_MODE_PARAMETER(DRM_MODE_ANALOG_PAL,
> > + PAL_LINES_NUMBER,
> > + PAL_LINE_DURATION_NS,
> > + PARAM_RANGE(PAL_HACT_DURATION_MIN_NS,
> > + PAL_HACT_DURATION_TYP_NS,
> > + PAL_HACT_DURATION_MAX_NS),
> > + PARAM_RANGE(PAL_HFP_DURATION_MIN_NS,
> > + PAL_HFP_DURATION_TYP_NS,
> > + PAL_HFP_DURATION_MAX_NS),
> > + PARAM_RANGE(PAL_HSLEN_DURATION_MIN_NS,
> > + PAL_HSLEN_DURATION_TYP_NS,
> > + PAL_HSLEN_DURATION_MAX_NS),
> > + PARAM_RANGE(PAL_HBP_DURATION_MIN_NS,
> > + PAL_HBP_DURATION_TYP_NS,
> > + PAL_HBP_DURATION_MAX_NS),
> > + PARAM_RANGE(PAL_HBLK_DURATION_MIN_NS,
> > + PAL_HBLK_DURATION_TYP_NS,
> > + PAL_HBLK_DURATION_MAX_NS),
> > + 12,
> > +
> > + /*
> > +  * The front porch is actually 6 short sync
> > +  * pulses for the even field, and 5 for the
> > +  * odd field. Each sync takes half a life so
> > +  * the odd field front porch is shorter by
> > +  * half a line.
> > +  *
> > +  * In progressive, we're supposed to use 6
> > +  * pulses, so we're fine there
> > +  */
> > + PARAM_FIELD(3, 2),
> > +
> > + /*
> > +  * The vsync length is 5 long sync pulses,
> > +  * each field taking half a line. We're
> > +  * shorter for both fields by half a line.
> > +  *
> > +  * In progressive, we're supposed to use 5
> > +  * pulses, so we're off by half
> > +  * a line.
> > +  *
> > +  * In interlace, we're now off by half a line
> > +  * for the even field and one line for the odd
> > +  * field.
> > +  */
> > + PARAM_FIELD(3, 3),
> > +
> > + /*
> > +  * The back porch starts with post-equalizing
> > +  * pulses, consisting in 5 short sync pulses
> > +  * for the even field, 4 for the odd field. In
> > +  * progressive, it's 5 short syncs.
> > +  *
> > +  * In progressive, we thus have 2.5 lines,
> > +  * plus the 0.5 line we were missing
> > +  * previously, so we should use 3 lines.
> > +  *
> > +  * In interlace, the even field is in the
> > +  * exact same case than progressive. For the
> > +  * odd field, we should be using 2 lines but
> > +  * we're one line short, so we'll make up for
> > +  * it here by using 3.
> > +  *
> > +  * The entire blanking area is supposed to
> > +  

Re: [PATCH v5 06/22] drm/modes: Add a function to generate analog display modes

2022-10-16 Thread Mateusz Kwiatkowski
Hi Maxime & everyone,

Sorry for being inactive in the discussions about this patchset for the last
couple of weeks.

> +const static struct analog_parameters tv_modes_parameters[] = {
> + TV_MODE_PARAMETER(DRM_MODE_ANALOG_NTSC,
> +   NTSC_LINES_NUMBER,
> +   NTSC_LINE_DURATION_NS,
> +   PARAM_RANGE(NTSC_HACT_DURATION_MIN_NS,
> +   NTSC_HACT_DURATION_TYP_NS,
> +   NTSC_HACT_DURATION_MAX_NS),
> +   PARAM_RANGE(NTSC_HFP_DURATION_MIN_NS,
> +   NTSC_HFP_DURATION_TYP_NS,
> +   NTSC_HFP_DURATION_MAX_NS),
> +   PARAM_RANGE(NTSC_HSLEN_DURATION_MIN_NS,
> +   NTSC_HSLEN_DURATION_TYP_NS,
> +   NTSC_HSLEN_DURATION_MAX_NS),
> +   PARAM_RANGE(NTSC_HBP_DURATION_MIN_NS,
> +   NTSC_HBP_DURATION_TYP_NS,
> +   NTSC_HBP_DURATION_MAX_NS),
> +   PARAM_RANGE(NTSC_HBLK_DURATION_MIN_NS,
> +   NTSC_HBLK_DURATION_TYP_NS,
> +   NTSC_HBLK_DURATION_MAX_NS),
> +   16,
> +   PARAM_FIELD(3, 3),
> +   PARAM_FIELD(3, 3),
> +   PARAM_FIELD(16, 17)),
> + TV_MODE_PARAMETER(DRM_MODE_ANALOG_PAL,
> +   PAL_LINES_NUMBER,
> +   PAL_LINE_DURATION_NS,
> +   PARAM_RANGE(PAL_HACT_DURATION_MIN_NS,
> +   PAL_HACT_DURATION_TYP_NS,
> +   PAL_HACT_DURATION_MAX_NS),
> +   PARAM_RANGE(PAL_HFP_DURATION_MIN_NS,
> +   PAL_HFP_DURATION_TYP_NS,
> +   PAL_HFP_DURATION_MAX_NS),
> +   PARAM_RANGE(PAL_HSLEN_DURATION_MIN_NS,
> +   PAL_HSLEN_DURATION_TYP_NS,
> +   PAL_HSLEN_DURATION_MAX_NS),
> +   PARAM_RANGE(PAL_HBP_DURATION_MIN_NS,
> +   PAL_HBP_DURATION_TYP_NS,
> +   PAL_HBP_DURATION_MAX_NS),
> +   PARAM_RANGE(PAL_HBLK_DURATION_MIN_NS,
> +   PAL_HBLK_DURATION_TYP_NS,
> +   PAL_HBLK_DURATION_MAX_NS),
> +   12,
> +
> +   /*
> +* The front porch is actually 6 short sync
> +* pulses for the even field, and 5 for the
> +* odd field. Each sync takes half a life so
> +* the odd field front porch is shorter by
> +* half a line.
> +*
> +* In progressive, we're supposed to use 6
> +* pulses, so we're fine there
> +*/
> +   PARAM_FIELD(3, 2),
> +
> +   /*
> +* The vsync length is 5 long sync pulses,
> +* each field taking half a line. We're
> +* shorter for both fields by half a line.
> +*
> +* In progressive, we're supposed to use 5
> +* pulses, so we're off by half
> +* a line.
> +*
> +* In interlace, we're now off by half a line
> +* for the even field and one line for the odd
> +* field.
> +*/
> +   PARAM_FIELD(3, 3),
> +
> +   /*
> +* The back porch starts with post-equalizing
> +* pulses, consisting in 5 short sync pulses
> +* for the even field, 4 for the odd field. In
> +* progressive, it's 5 short syncs.
> +*
> +* In progressive, we thus have 2.5 lines,
> +* plus the 0.5 line we were missing
> +* previously, so we should use 3 lines.
> +*
> +* In interlace, the even field is in the
> +* exact same case than progressive. For the
> +* odd field, we should be using 2 lines but
> +* we're one line short, so we'll make up for
> +* it here by using 3.
> +*
> +* The entire blanking area is supposed to
> +* take 25 lines, so we also need to account
> +*

[PATCH v5 06/22] drm/modes: Add a function to generate analog display modes

2022-10-13 Thread Maxime Ripard
Multiple drivers (meson, vc4, sun4i) define analog TV 525-lines and
625-lines modes in their drivers.

Since those modes are fairly standard, and that we'll need to use them
in more places in the future, it makes sense to move their definition
into the core framework.

However, analog display usually have fairly loose timings requirements,
the only discrete parameters being the total number of lines and pixel
clock frequency. Thus, we created a function that will create a display
mode from the standard, the pixel frequency and the active area.

Signed-off-by: Maxime Ripard 

---

Changes in v4:
- Reworded the line length check comment
- Switch to HZ_PER_KHZ in tests
- Use previous timing to fill our mode
- Move the number of lines check earlier
---
 drivers/gpu/drm/drm_modes.c| 474 +
 drivers/gpu/drm/tests/Makefile |   1 +
 drivers/gpu/drm/tests/drm_modes_test.c | 144 ++
 include/drm/drm_modes.h|  17 ++
 4 files changed, 636 insertions(+)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 5d4ac79381c4..c0dceff51cac 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -116,6 +116,480 @@ void drm_mode_probed_add(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_mode_probed_add);
 
+enum drm_mode_analog {
+   DRM_MODE_ANALOG_NTSC, /* 525 lines, 60Hz */
+   DRM_MODE_ANALOG_PAL, /* 625 lines, 50Hz */
+};
+
+/*
+ * The timings come from:
+ * - 
https://web.archive.org/web/20220406232708/http://www.kolumbus.fi/pami1/video/pal_ntsc.html
+ * - 
https://web.archive.org/web/20220406124914/http://martin.hinner.info/vga/pal.html
+ * - 
https://web.archive.org/web/20220609202433/http://www.batsocks.co.uk/readme/video_timing.htm
+ */
+#define NTSC_LINE_DURATION_NS  63556U
+#define NTSC_LINES_NUMBER  525
+
+#define NTSC_HBLK_DURATION_TYP_NS  10900U
+#define NTSC_HBLK_DURATION_MIN_NS  (NTSC_HBLK_DURATION_TYP_NS - 200)
+#define NTSC_HBLK_DURATION_MAX_NS  (NTSC_HBLK_DURATION_TYP_NS + 200)
+
+#define NTSC_HACT_DURATION_TYP_NS  (NTSC_LINE_DURATION_NS - 
NTSC_HBLK_DURATION_TYP_NS)
+#define NTSC_HACT_DURATION_MIN_NS  (NTSC_LINE_DURATION_NS - 
NTSC_HBLK_DURATION_MAX_NS)
+#define NTSC_HACT_DURATION_MAX_NS  (NTSC_LINE_DURATION_NS - 
NTSC_HBLK_DURATION_MIN_NS)
+
+#define NTSC_HFP_DURATION_TYP_NS   1500
+#define NTSC_HFP_DURATION_MIN_NS   1270
+#define NTSC_HFP_DURATION_MAX_NS   2220
+
+#define NTSC_HSLEN_DURATION_TYP_NS 4700
+#define NTSC_HSLEN_DURATION_MIN_NS (NTSC_HSLEN_DURATION_TYP_NS - 100)
+#define NTSC_HSLEN_DURATION_MAX_NS (NTSC_HSLEN_DURATION_TYP_NS + 100)
+
+#define NTSC_HBP_DURATION_TYP_NS   4700
+
+/*
+ * I couldn't find the actual tolerance for the back porch, so let's
+ * just reuse the sync length ones.
+ */
+#define NTSC_HBP_DURATION_MIN_NS   (NTSC_HBP_DURATION_TYP_NS - 100)
+#define NTSC_HBP_DURATION_MAX_NS   (NTSC_HBP_DURATION_TYP_NS + 100)
+
+#define PAL_LINE_DURATION_NS   64000U
+#define PAL_LINES_NUMBER   625
+
+#define PAL_HACT_DURATION_TYP_NS   51950U
+#define PAL_HACT_DURATION_MIN_NS   (PAL_HACT_DURATION_TYP_NS - 100)
+#define PAL_HACT_DURATION_MAX_NS   (PAL_HACT_DURATION_TYP_NS + 400)
+
+#define PAL_HBLK_DURATION_TYP_NS   (PAL_LINE_DURATION_NS - 
PAL_HACT_DURATION_TYP_NS)
+#define PAL_HBLK_DURATION_MIN_NS   (PAL_LINE_DURATION_NS - 
PAL_HACT_DURATION_MAX_NS)
+#define PAL_HBLK_DURATION_MAX_NS   (PAL_LINE_DURATION_NS - 
PAL_HACT_DURATION_MIN_NS)
+
+#define PAL_HFP_DURATION_TYP_NS1650
+#define PAL_HFP_DURATION_MIN_NS(PAL_HFP_DURATION_TYP_NS - 100)
+#define PAL_HFP_DURATION_MAX_NS(PAL_HFP_DURATION_TYP_NS + 400)
+
+#define PAL_HSLEN_DURATION_TYP_NS  4700
+#define PAL_HSLEN_DURATION_MIN_NS  (PAL_HSLEN_DURATION_TYP_NS - 200)
+#define PAL_HSLEN_DURATION_MAX_NS  (PAL_HSLEN_DURATION_TYP_NS + 200)
+
+#define PAL_HBP_DURATION_TYP_NS5700
+#define PAL_HBP_DURATION_MIN_NS(PAL_HBP_DURATION_TYP_NS - 200)
+#define PAL_HBP_DURATION_MAX_NS(PAL_HBP_DURATION_TYP_NS + 200)
+
+struct analog_param_field {
+   unsigned int even, odd;
+};
+
+#define PARAM_FIELD(_odd, _even)   \
+   { .even = _even, .odd = _odd }
+
+struct analog_param_range {
+   unsigned intmin, typ, max;
+};
+
+#define PARAM_RANGE(_min, _typ, _max)  \
+   { .min = _min, .typ = _typ, .max = _max }
+
+struct analog_parameters {
+   unsigned intnum_lines;
+   unsigned intline_duration_ns;
+
+   struct analog_param_range   hact_ns;
+   struct analog_param_range   hfp_ns;
+   struct analog_param_range   hslen_ns;
+   struct analog_param_range   hbp_ns;
+   struct analog_param_range   hblk_ns;
+
+   unsigned intbt601_hfp;
+
+   struct analog_param_field