Message ID | 20180302134804.3690-4-bparrot@ti.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Benoit, On 02/03/18 15:48, Benoit Parrot wrote: > Virtual planes are used to extend display size capability for display > larger than 2048 pixels by splitting the frame buffer equally between > two physical planes. > > Here we are adding DT support to parse 'plane' child nodes which > describe how logical planes are mapped to physical plane(s) and > which crtc they are available on. > > Signed-off-by: Benoit Parrot <bparrot@ti.com> > --- > 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 624dee22f46b..559b70d9762d 100644 > --- a/drivers/gpu/drm/omapdrm/dss/dispc.c > +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c > @@ -4334,6 +4334,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) > + break; I think the flow is more readable, if here you "return plane", and at the end of the func "return NULL". > + } > + > + return plane; > +} > + > +static int dispc_parse_dt_plane_data(struct dispc_plane_mappings *plane) You could rename the parameter to "map", for example. Using 'plane' there is quite confusing. > +{ > + 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(); > + unsigned long int hw_plane_mask = (1 << num_ovls) - 1; u32? > + 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, "hw-planes")) { > + dev_err(&pdev->dev, > + "malformed plane node: hw-planes missing.\n"); > + return -EINVAL; > + } > + > + index = 0; > + of_property_for_each_u32(ep, "hw-planes", prop, cur, v) { > + if (v >= num_ovls) { > + dev_err(&pdev->dev, > + "hw-planes property: '%d' out-of-range.\n", > + v); > + return -EINVAL; > + } > + if (!(hw_plane_mask & BIT_MASK(v))) { > + dev_err(&pdev->dev, > + "hw-planes property: '%d' used more than once.\n", > + v); > + return -EINVAL; > + } > + clear_bit(v, &hw_plane_mask); Why do you use hw_plane_mask this way? It feels inverse to me, usually one sets a bit when something is there. And e.g. crtc_mask here is used the other way. > + > + if (index == 0) { > + plane->plane[i].main_id = v; > + } else if (index == 1) { > + plane->plane[i].aux_id = v; > + plane->plane[i].is_virtual = true; > + } else if (index > 1) { > + dev_err(&pdev->dev, > + "hw-planes property: more than 2 values specified.\n"); > + return -EINVAL; > + } > + index++; > + } > + > + of_property_for_each_u32(ep, "hw-crtcs", prop, cur, v) { > + if (v >= num_ovls) { This should check against num_ovl_mgrs. > + dev_err(&pdev->dev, > + "hw-crtcs property: '%d' out-of-range.\n", > + v); > + return -EINVAL; > + } > + plane->plane[i].crtc_mask |= 1 << v; > + } > + } > + > + num_planes = i; > + > + if (num_planes) { > + dev_dbg(&pdev->dev, "Plane definitions found from DT:"); > + for (i = 0; i < num_planes; i++) { > + if (plane->plane[i].is_virtual) { > + dev_dbg(&pdev->dev, > + "plane%d: virtual hw-planes: %d, %d crtc_mask: 0x%04x", > + i, plane->plane[i].main_id, > + plane->plane[i].aux_id, > + plane->plane[i].crtc_mask); > + } else { > + dev_dbg(&pdev->dev, > + "plane%d: hw-planes: %d crtc_mask: 0x%04x", > + i, plane->plane[i].main_id, > + plane->plane[i].crtc_mask); > + } > + } > + } > + > + plane->num_planes = num_planes; > + > + return 0; > +} > + > /* > * Workaround for errata i734 in DSS dispc > * - LCD1 Gamma Correction Is Not Working When GFX Pipe Is Disabled > @@ -4525,6 +4634,7 @@ static const struct dispc_ops dispc_ops = { > .ovl_enable = dispc_ovl_enable, > .ovl_setup = dispc_ovl_setup, > .ovl_get_color_modes = dispc_ovl_get_color_modes, > + .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 f8f83e826a56..b8c9b30bf5ed 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; is_virtual has a tab whereas the others don't. Tomi
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 624dee22f46b..559b70d9762d 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -4334,6 +4334,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) + break; + } + + return plane; +} + +static int dispc_parse_dt_plane_data(struct dispc_plane_mappings *plane) +{ + 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(); + unsigned long int hw_plane_mask = (1 << num_ovls) - 1; + 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, "hw-planes")) { + dev_err(&pdev->dev, + "malformed plane node: hw-planes missing.\n"); + return -EINVAL; + } + + index = 0; + of_property_for_each_u32(ep, "hw-planes", prop, cur, v) { + if (v >= num_ovls) { + dev_err(&pdev->dev, + "hw-planes property: '%d' out-of-range.\n", + v); + return -EINVAL; + } + if (!(hw_plane_mask & BIT_MASK(v))) { + dev_err(&pdev->dev, + "hw-planes property: '%d' used more than once.\n", + v); + return -EINVAL; + } + clear_bit(v, &hw_plane_mask); + + if (index == 0) { + plane->plane[i].main_id = v; + } else if (index == 1) { + plane->plane[i].aux_id = v; + plane->plane[i].is_virtual = true; + } else if (index > 1) { + dev_err(&pdev->dev, + "hw-planes property: more than 2 values specified.\n"); + return -EINVAL; + } + index++; + } + + of_property_for_each_u32(ep, "hw-crtcs", prop, cur, v) { + if (v >= num_ovls) { + dev_err(&pdev->dev, + "hw-crtcs property: '%d' out-of-range.\n", + v); + return -EINVAL; + } + plane->plane[i].crtc_mask |= 1 << v; + } + } + + num_planes = i; + + if (num_planes) { + dev_dbg(&pdev->dev, "Plane definitions found from DT:"); + for (i = 0; i < num_planes; i++) { + if (plane->plane[i].is_virtual) { + dev_dbg(&pdev->dev, + "plane%d: virtual hw-planes: %d, %d crtc_mask: 0x%04x", + i, plane->plane[i].main_id, + plane->plane[i].aux_id, + plane->plane[i].crtc_mask); + } else { + dev_dbg(&pdev->dev, + "plane%d: hw-planes: %d crtc_mask: 0x%04x", + i, plane->plane[i].main_id, + plane->plane[i].crtc_mask); + } + } + } + + plane->num_planes = num_planes; + + return 0; +} + /* * Workaround for errata i734 in DSS dispc * - LCD1 Gamma Correction Is Not Working When GFX Pipe Is Disabled @@ -4525,6 +4634,7 @@ static const struct dispc_ops dispc_ops = { .ovl_enable = dispc_ovl_enable, .ovl_setup = dispc_ovl_setup, .ovl_get_color_modes = dispc_ovl_get_color_modes, + .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 f8f83e826a56..b8c9b30bf5ed 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); @@ -719,6 +729,7 @@ struct dispc_ops { enum omap_channel channel); const u32 *(*ovl_get_color_modes)(enum omap_plane_id plane); + int (*get_plane_mapping)(struct dispc_plane_mappings *plane); }; void dispc_set_ops(const struct dispc_ops *o);
Virtual planes are used to extend display size capability for display larger than 2048 pixels by splitting the frame buffer equally between two physical planes. Here we are adding DT support to parse 'plane' child nodes which describe how logical planes are mapped to physical plane(s) and which crtc they are available on. Signed-off-by: Benoit Parrot <bparrot@ti.com> --- drivers/gpu/drm/omapdrm/dss/dispc.c | 110 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/omapdrm/dss/omapdss.h | 11 ++++ 2 files changed, 121 insertions(+)