Virtual planes are used to extend display size capability for display larger than 2048 pixels by splitting the frame buffer equally between two physical video-pipelines. Here we are adding DT support to parse 'plane' child nodes which describe how logical planes are mapped to physical video-pipeline(s) and which video-outputs they are available on. Signed-off-by: Benoit Parrot <bparrot@xxxxxx> --- drivers/gpu/drm/omapdrm/dss/dispc.c | 110 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/omapdrm/dss/omapdss.h | 11 ++++ 2 files changed, 121 insertions(+) diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 35541d4441df..06a2e894175e 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -4360,6 +4360,115 @@ static u32 dispc_get_memory_bandwidth_limit(void) return limit; } +static struct device_node *dispc_of_get_plane_by_id(struct device_node *node, + u32 id) +{ + struct device_node *plane; + + for_each_child_of_node(node, plane) { + u32 plane_id = 0; + + if (of_node_cmp(plane->name, "plane") != 0) + continue; + of_property_read_u32(plane, "reg", &plane_id); + if (id == plane_id) + return plane; + } + + return NULL; +} + +static int dispc_parse_dt_plane_data(struct dispc_plane_mappings *map) +{ + struct platform_device *pdev = dispc.pdev; + struct device_node *np = pdev->dev.of_node; + struct device_node *ep; + struct property *prop; + const __be32 *cur; + u32 v; + u32 num_ovls = dispc_get_num_ovls(); + u32 hw_plane_mask = 0; + u32 num_planes; + int i, index; + + if (!np) + return 0; + + for (i = 0; i < num_ovls; i++) { + ep = dispc_of_get_plane_by_id(np, i); + if (!ep) + break; + if (!of_property_read_bool(ep, "video-pipelines")) { + dev_err(&pdev->dev, + "malformed plane node: video-pipelines missing.\n"); + return -EINVAL; + } + + index = 0; + of_property_for_each_u32(ep, "video-pipelines", prop, cur, v) { + if (v >= num_ovls) { + dev_err(&pdev->dev, + "video-pipelines property: '%d' out-of-range.\n", + v); + return -EINVAL; + } + if (hw_plane_mask & BIT_MASK(v)) { + dev_err(&pdev->dev, + "video-pipelines property: '%d' used more than once.\n", + v); + return -EINVAL; + } + hw_plane_mask |= BIT(v); + + if (index == 0) { + map->plane[i].main_id = v; + } else if (index == 1) { + map->plane[i].aux_id = v; + map->plane[i].is_virtual = true; + } else if (index > 1) { + dev_err(&pdev->dev, + "video-pipelines property: more than 2 values specified.\n"); + return -EINVAL; + } + index++; + } + + of_property_for_each_u32(ep, "video-outputs", prop, cur, v) { + if (v >= dispc_get_num_mgrs()) { + dev_err(&pdev->dev, + "video-outputs property: '%d' out-of-range.\n", + v); + return -EINVAL; + } + map->plane[i].crtc_mask |= BIT(v); + } + } + + num_planes = i; + + if (num_planes) { + dev_dbg(&pdev->dev, "Plane definitions found from DT:"); + for (i = 0; i < num_planes; i++) { + if (map->plane[i].is_virtual) { + dev_dbg(&pdev->dev, + "plane%d: virtual video-pipelines: %d, %d video-output mask: 0x%04x", + i, map->plane[i].main_id, + map->plane[i].aux_id, + map->plane[i].crtc_mask); + } else { + dev_dbg(&pdev->dev, + "plane%d: video-pipelines: %d video-output mask: 0x%04x", + i, map->plane[i].main_id, + map->plane[i].crtc_mask); + } + } + } + + map->num_planes = num_planes; + + return 0; +} + /* * Workaround for errata i734 in DSS dispc * - LCD1 Gamma Correction Is Not Working When GFX Pipe Is Disabled @@ -4552,6 +4661,7 @@ static const struct dispc_ops dispc_ops = { .ovl_setup = dispc_ovl_setup, .ovl_get_color_modes = dispc_ovl_get_color_modes, .ovl_get_max_size = dispc_ovl_get_max_size, + .get_plane_mapping = dispc_parse_dt_plane_data, }; /* DISPC HW IP initialisation */ diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index c58c75292182..ad0f751ec047 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -637,6 +637,16 @@ void omapdss_set_is_initialized(bool set); struct device_node *dss_of_port_get_parent_device(struct device_node *port); u32 dss_of_port_get_port_number(struct device_node *port); +struct dispc_plane_mappings { + struct { + u32 main_id; + u32 aux_id; + u32 crtc_mask; + bool is_virtual; + } plane[4]; + u32 num_planes; +}; + struct dss_mgr_ops { int (*connect)(enum omap_channel channel, struct omap_dss_device *dst); @@ -720,6 +730,7 @@ struct dispc_ops { const u32 *(*ovl_get_color_modes)(enum omap_plane_id plane); void (*ovl_get_max_size)(u16 *width, u16 *height); + int (*get_plane_mapping)(struct dispc_plane_mappings *plane); }; void dispc_set_ops(const struct dispc_ops *o); -- 2.9.0 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html