[PATCH 1/2 v6] of: add helper to parse display timings

Stephen Warren swarren at wwwdotorg.org
Fri Oct 5 04:47:16 EST 2012


On 10/04/2012 11:59 AM, Steffen Trumtrar wrote:

A patch description would be useful for something like this.

> diff --git a/Documentation/devicetree/bindings/video/display-timings.txt b/Documentation/devicetree/bindings/video/display-timings.txt
> new file mode 100644
...
> +Usage in backend
> +================

Everything before that point in the file looks fine to me.

Everything after this point in the file seems to be Linux-specific
implementation details. Does it really belong in the DT binding
documentation, rather than some Linux-specific documentation file?

> +struct drm_display_mode
> +=======================
> +
> +  +----------+---------------------------------------------+----------+-------+
> +  |          |                                             |          |       |  ↑
> +  |          |                                             |          |       |  |
> +  |          |                                             |          |       |  |
> +  +----------###############################################----------+-------+  |

I suspect the entire horizontal box above (and the entire vertical box
all the way down the left-hand side) should be on the bottom/right
instead of top/left. The reason I think this is because all of
vsync_start, vsync_end, vdisplay have to be referenced to some known
point, which is usually zero or the start of the timing definition, /or/
there would be some value indicating the size of the top marging/porch
in order to say where those other values are referenced to.

> +  |          #   ↑         ↑          ↑                    #          |       |  |
> +  |          #   |         |          |                    #          |       |  |
> +  |          #   |         |          |                    #          |       |  |
> +  |          #   |         |          |                    #          |       |  |
> +  |          #   |         |          |                    #          |       |  |
> +  |          #   |         |          |       hdisplay     #          |       |  |
> +  |          #<--+--------------------+------------------->#          |       |  |
> +  |          #   |         |          |                    #          |       |  |
> +  |          #   |vsync_start         |                    #          |       |  |
> +  |          #   |         |          |                    #          |       |  |
> +  |          #   |         |vsync_end |                    #          |       |  |
> +  |          #   |         |          |vdisplay            #          |       |  |
> +  |          #   |         |          |                    #          |       |  |
> +  |          #   |         |          |                    #          |       |  |
> +  |          #   |         |          |                    #          |       |  | vtotal
> +  |          #   |         |          |                    #          |       |  |
> +  |          #   |         |          |     hsync_start    #          |       |  |
> +  |          #<--+---------+----------+------------------------------>|       |  |
> +  |          #   |         |          |                    #          |       |  |
> +  |          #   |         |          |     hsync_end      #          |       |  |
> +  |          #<--+---------+----------+-------------------------------------->|  |
> +  |          #   |         |          ↓                    #          |       |  |
> +  +----------####|#########|################################----------+-------+  |
> +  |          |   |         |                               |          |       |  |
> +  |          |   |         |                               |          |       |  |
> +  |          |   ↓         |                               |          |       |  |
> +  +----------+-------------+-------------------------------+----------+-------+  |
> +  |          |             |                               |          |       |  |
> +  |          |             |                               |          |       |  |
> +  |          |             ↓                               |          |       |  ↓
> +  +----------+---------------------------------------------+----------+-------+
> +                                   htotal
> +   <------------------------------------------------------------------------->

> diff --git a/drivers/of/of_display_timings.c b/drivers/of/of_display_timings.c

> +static int parse_property(struct device_node *np, char *name,
> +				struct timing_entry *result)

> +	if (cells == 1)
> +		ret = of_property_read_u32_array(np, name, &result->typ, cells);

Should that branch not just set result->min/max to typ as well?
Presumably it'd prevent any code that interprets struct timing_entry
from having to check if those values were 0 or not?

> +	else if (cells == 3)
> +		ret = of_property_read_u32_array(np, name, &result->min, cells);

> +struct display_timings *of_get_display_timing_list(struct device_node *np)

> +	entry = of_parse_phandle(timings_np, "default-timing", 0);
> +
> +	if (!entry) {
> +		pr_info("%s: no default-timing specified\n", __func__);
> +		entry = of_find_node_by_name(np, "timing");

I don't think you want to require the node have an explicit name; I
don't recall the DT binding documentation making that a requirement.
Instead, can't you either just leave the default unset, or pick the
first DT child node, irrespective of name?

> +	if (!entry) {
> +		pr_info("%s: no timing specifications given\n", __func__);
> +		return disp;
> +	}

The DT bindings don't state that it's mandatory to have some timing
specified, although I agree that it makes sense in practice.

> +	for_each_child_of_node(timings_np, entry) {
> +		struct signal_timing *st;
> +
> +		st = of_get_display_timing(entry);
> +
> +		if (!st)
> +			continue;

I wonder if that shouldn't be an error?

> +		if (strcmp(default_timing, entry->full_name) == 0)
> +			disp->default_timing = disp->num_timings;

Hmm. Why not compare the node pointers rather than the name? Also, if
the parsing failed, then this can lead to default_timing being
uninitialized anyway...

> +		disp->timings[disp->num_timings] = st;
> +		disp->num_timings++;
> +	}

> +	if (disp->num_timings >= 0)
> +		pr_info("%s: got %d timings. Using timing #%d as default\n", __func__,
> +			disp->num_timings , disp->default_timing + 1);
> +	else
> +		pr_info("%s: no timings specified\n", __func__);

The message in the else clause is not necessarily true; there may have
been some specified, but they just couldn't be parsed.

> +int of_display_timings_exists(struct device_node *np)
> +{
> +	struct device_node *timings_np;
> +	struct device_node *default_np;
> +
> +	if (!np)
> +		return -EINVAL;
> +
> +	timings_np = of_parse_phandle(np, "display-timings", 0);
> +
> +	if (!timings_np)
> +		return -EINVAL;
> +
> +	default_np = of_parse_phandle(np, "default-timing", 0);
> +
> +	if (default_np)
> +		return 0;

If this function checks that a default-timing property exists, shouldn't
the function be named of_display_default_timing_exists()?


More information about the devicetree-discuss mailing list