]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
video: simple_panel: add EDID support
authorSvyatoslav Ryhel <clamor95@gmail.com>
Mon, 8 Jan 2024 16:45:01 +0000 (18:45 +0200)
committerAnatolij Gustschin <agust@denx.de>
Sun, 21 Apr 2024 07:04:03 +0000 (09:04 +0200)
Support timing parsing from EDID if panel device tree node
provides DDC i2c bus instead of timings node.

Tested-by: Robert Eckelmann <longnoserob@gmail.com> # ASUS TF201
Tested-by: Agneli <poczt@protonmail.ch> # Toshiba AC100 T20
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
[agust: reworked to fix dm_i2c_* build errors and to big img size]
Signed-off-by: Anatolij Gustschin <agust@denx.de>
drivers/video/simple_panel.c

index 064c113d2d0905e3d41c1ad26a96812d31cc5f17..76a30427a59f2efa57230e54b0ce8a423aaa816f 100644 (file)
@@ -7,12 +7,16 @@
 #include <common.h>
 #include <backlight.h>
 #include <dm.h>
+#include <edid.h>
+#include <i2c.h>
 #include <log.h>
 #include <mipi_dsi.h>
 #include <panel.h>
 #include <asm/gpio.h>
 #include <power/regulator.h>
 
+#define EDID_I2C_ADDR  0x50
+
 struct simple_panel_priv {
        struct udevice *reg;
        struct udevice *backlight;
@@ -49,13 +53,71 @@ static int simple_panel_set_backlight(struct udevice *dev, int percent)
        return 0;
 }
 
+#if CONFIG_IS_ENABLED(I2C_EDID) && CONFIG_IS_ENABLED(DM_I2C)
+static int simple_panel_get_edid_timing(struct udevice *dev,
+                                       struct display_timing *timings)
+{
+       struct udevice *panel_ddc, *panel_edid;
+       struct display_timing edid_timing;
+       u8 edid_buf[EDID_SIZE] = { 0 };
+       int ret, bpc;
+       /* Check for DDC i2c if no timings are provided */
+       ret = uclass_get_device_by_phandle(UCLASS_I2C, dev,
+                                          "ddc-i2c-bus",
+                                          &panel_ddc);
+       if (ret) {
+               log_debug("%s: cannot get DDC i2c bus: error %d\n",
+                         __func__, ret);
+               return ret;
+       }
+
+       ret = dm_i2c_probe(panel_ddc, EDID_I2C_ADDR, 0, &panel_edid);
+       if (ret) {
+               log_debug("%s: cannot probe EDID: error %d\n",
+                         __func__, ret);
+               return ret;
+       }
+
+       ret = dm_i2c_read(panel_edid, 0, edid_buf, sizeof(edid_buf));
+       if (ret) {
+               log_debug("%s: cannot dump EDID buffer: error %d\n",
+                         __func__, ret);
+               return ret;
+       }
+
+       ret = edid_get_timing(edid_buf, sizeof(edid_buf),
+                             &edid_timing, &bpc);
+       if (ret) {
+               log_debug("%s: cannot decode EDID info: error %d\n",
+                         __func__, ret);
+               return ret;
+       }
+
+       memcpy(timings, &edid_timing, sizeof(*timings));
+
+       return 0;
+}
+#else
+static int simple_panel_get_edid_timing(struct udevice *dev,
+                                       struct display_timing *timings)
+{
+       return -ENOTSUPP;
+}
+#endif
+
 static int simple_panel_get_display_timing(struct udevice *dev,
                                           struct display_timing *timings)
 {
        const void *blob = gd->fdt_blob;
+       int ret;
+
+       /* Check for timing subnode if panel node first */
+       ret = fdtdec_decode_display_timing(blob, dev_of_offset(dev),
+                                          0, timings);
+       if (!ret)
+               return ret;
 
-       return fdtdec_decode_display_timing(blob, dev_of_offset(dev),
-                                           0, timings);
+       return simple_panel_get_edid_timing(dev, timings);
 }
 
 static int simple_panel_of_to_plat(struct udevice *dev)