summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/sysfb/ofdrm.c
diff options
context:
space:
mode:
authorThomas Zimmermann <tzimmermann@suse.de>2025-04-01 11:37:15 +0200
committerThomas Zimmermann <tzimmermann@suse.de>2025-04-07 11:02:07 +0200
commite7f435b3dcf7f290fa97538ec26b41c1d2eff138 (patch)
tree9afa3424a44fe7856a381feb72608bbb31362099 /drivers/gpu/drm/sysfb/ofdrm.c
parent177dfbdb7e67db24d86dbd41cde20813d6e820cc (diff)
drm/sysfb: ofdrm: Add EDID support
Add EDID support to sysfb connector helpers. Read the EDID property from the OF node in ofdrm. Without EDID, this does nothing. Some systems with OF display, such as 32-bit PPC Macintoshs, provide the system display's EDID data as node property in their DT. Exporting this information allows compositors to implement correct DPI and meaningful color management. v3: - avoid parser error by clearing EDID extension field v2: - return errno codes on errors (Jani) - simplify EDID read logic (Jani) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Link: https://lore.kernel.org/r/20250401094056.32904-13-tzimmermann@suse.de
Diffstat (limited to 'drivers/gpu/drm/sysfb/ofdrm.c')
-rw-r--r--drivers/gpu/drm/sysfb/ofdrm.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/gpu/drm/sysfb/ofdrm.c b/drivers/gpu/drm/sysfb/ofdrm.c
index 71e661ba9329..86c1a0c80ceb 100644
--- a/drivers/gpu/drm/sysfb/ofdrm.c
+++ b/drivers/gpu/drm/sysfb/ofdrm.c
@@ -12,6 +12,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
+#include <drm/drm_edid.h>
#include <drm/drm_fbdev_shmem.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
@@ -227,6 +228,16 @@ static u64 display_get_address_of(struct drm_device *dev, struct device_node *of
return address;
}
+static const u8 *display_get_edid_of(struct drm_device *dev, struct device_node *of_node,
+ u8 buf[EDID_LENGTH])
+{
+ int ret = of_property_read_u8_array(of_node, "EDID", buf, EDID_LENGTH);
+
+ if (ret)
+ return NULL;
+ return buf;
+}
+
static bool is_avivo(u32 vendor, u32 device)
{
/* This will match most R5xx */
@@ -298,6 +309,8 @@ struct ofdrm_device {
/* colormap */
void __iomem *cmap_base;
+ u8 edid[EDID_LENGTH];
+
/* modesetting */
u32 formats[DRM_SYSFB_PLANE_NFORMATS(1)];
struct drm_plane primary_plane;
@@ -840,6 +853,7 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv,
int width, height, depth, linebytes;
const struct drm_format_info *format;
u64 address;
+ const u8 *edid;
resource_size_t fb_size, fb_base, fb_pgbase, fb_pgsize;
struct resource *res, *mem;
void __iomem *screen_base;
@@ -989,6 +1003,9 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv,
}
}
+ /* EDID is optional */
+ edid = display_get_edid_of(dev, of_node, odev->edid);
+
/*
* Firmware framebuffer
*/
@@ -999,6 +1016,7 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv,
sysfb->fb_pitch = linebytes;
if (odev->cmap_base)
sysfb->fb_gamma_lut_size = OFDRM_GAMMA_LUT_SIZE;
+ sysfb->edid = edid;
drm_dbg(dev, "display mode={" DRM_MODE_FMT "}\n", DRM_MODE_ARG(&sysfb->fb_mode));
drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, linebytes=%d byte\n",
@@ -1072,6 +1090,8 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv,
drm_connector_set_panel_orientation_with_quirk(connector,
DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
width, height);
+ if (edid)
+ drm_connector_attach_edid_property(connector);
ret = drm_connector_attach_encoder(connector, encoder);
if (ret)