video: meson: Add fallback to default timings for QHD/UHD monitors
authorSylwester Nawrocki <s.nawrocki@samsung.com>
Wed, 25 Nov 2020 19:13:55 +0000 (20:13 +0100)
committerJaehoon Chung <jh80.chung@samsung.com>
Tue, 17 Oct 2023 04:19:27 +0000 (13:19 +0900)
The HDMI driver currently supports only up to 1920x1200 resolutions
and QHD/UHD monitors might not specify detailed timings in EDID other
than those for their maximum resolution, even though they work with
lower resolutions like full HD. In such cases display_read_timings()
will fail breaking the video output driver initialization.

As a workaround fallback to full HD timings is added for QHD or UHD
monitors. The default timing will only be used when "hdmimode"
environment variable is set to "1080p60hz", otherwise the driver
switches to CVBS mode as before, when display timings are
unsupported/could not be read.

The proper solution would be to implement support for 2K/4K HDMI
modes, which are also not supported yet by driver in the kernel.

Change-Id: I407228392a6b1b6e8b0c55a6962235111df0c69c
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
drivers/video/meson/meson_vpu.c

index 67d4ce7..6fb6241 100644 (file)
@@ -34,6 +34,20 @@ static struct meson_framebuffer {
        bool is_cvbs;
 } meson_fb = { 0 };
 
+
+static struct display_timing default_timing_1920x1080 = {
+       .pixelclock = { .typ = 148500000 },
+       .hactive = { .typ = 1920 },
+       .hfront_porch = { .typ = 88 },
+       .hback_porch = { .typ = 148 },
+       .hsync_len = { .typ = 44 },
+       .vactive = { .typ = 1080 },
+       .vfront_porch = { .typ = 4 },
+       .vback_porch = { .typ = 36 },
+       .vsync_len = { .typ = 5 },
+       .flags = DISPLAY_FLAGS_DE_LOW,
+};
+
 bool meson_vpu_is_compatible(struct meson_vpu_priv *priv,
                             enum vpu_compatible family)
 {
@@ -46,28 +60,38 @@ static int meson_vpu_setup_mode(struct udevice *dev, struct udevice *disp)
 {
        struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
        struct video_priv *uc_priv = dev_get_uclass_priv(dev);
-       struct display_timing timing;
+       struct display_timing disp_timing;
+       struct display_timing *timing = &disp_timing;
        bool is_cvbs = false;
        int ret = 0;
 
        if (disp) {
-               ret = display_read_timing(disp, &timing);
+               ret = display_read_timing(disp, timing);
                if (ret) {
-                       debug("%s: Failed to read timings\n", __func__);
-                       goto cvbs;
+                       char *env;
+
+                       printf("%s: Unsupported display timings\n", __func__);
+
+                       env = env_get("hdmimode");
+                       if (!env || strcmp(env, "1080p60hz"))
+                               goto cvbs;
+
+                       printf("%s: Using default full HD timings\n", __func__);
+
+                       timing = &default_timing_1920x1080;
                }
 
-               uc_priv->xsize = timing.hactive.typ;
-               uc_priv->ysize = timing.vactive.typ;
+               uc_priv->xsize = timing->hactive.typ;
+               uc_priv->ysize = timing->vactive.typ;
 
-               ret = display_enable(disp, 0, &timing);
+               ret = display_enable(disp, 0, timing);
                if (ret)
                        goto cvbs;
        } else {
 cvbs:
                /* CVBS has a fixed 720x480i (NTSC) and 720x576i (PAL) */
                is_cvbs = true;
-               timing.flags = DISPLAY_FLAGS_INTERLACED;
+               timing->flags = DISPLAY_FLAGS_INTERLACED;
                uc_priv->xsize = 720;
                uc_priv->ysize = 576;
        }
@@ -88,9 +112,9 @@ cvbs:
        /* Override the framebuffer address */
        uc_plat->base = meson_fb.base;
 
-       meson_vpu_setup_plane(dev, timing.flags & DISPLAY_FLAGS_INTERLACED);
-       meson_vpu_setup_venc(dev, &timing, is_cvbs);
-       meson_vpu_setup_vclk(dev, &timing, is_cvbs);
+       meson_vpu_setup_plane(dev, timing->flags & DISPLAY_FLAGS_INTERLACED);
+       meson_vpu_setup_venc(dev, timing, is_cvbs);
+       meson_vpu_setup_vclk(dev, timing, is_cvbs);
 
        video_set_flush_dcache(dev, 1);