diff options
| author | Simon Glass <sjg@chromium.org> | 2015-04-14 21:03:21 -0600 | 
|---|---|---|
| committer | Tom Warren <twarren@nvidia.com> | 2015-05-13 09:24:06 -0700 | 
| commit | 12e671142daa5d4dce5961e6f573a8b740b16f88 (patch) | |
| tree | 30eafbb47ee45d9de1683074067fd573163a0c20 /lib/fdtdec.c | |
| parent | 962f5caf600c54f4103bfa6b31fa2fb4e8aaacb9 (diff) | |
fdt: Add binding decode function for display-timings
This is useful for display parameters. Add a simple decode function to read
from this device tree node.
Signed-off-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Tom Warren <twarren@nvidia.com>
Diffstat (limited to 'lib/fdtdec.c')
| -rw-r--r-- | lib/fdtdec.c | 92 | 
1 files changed, 92 insertions, 0 deletions
| diff --git a/lib/fdtdec.c b/lib/fdtdec.c index b76d9cad83f..1007fa03723 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1037,6 +1037,98 @@ int fdtdec_decode_memory_region(const void *blob, int config_node,  	return 0;  } +static int decode_timing_property(const void *blob, int node, const char *name, +				  struct timing_entry *result) +{ +	int length, ret = 0; +	const u32 *prop; + +	prop = fdt_getprop(blob, node, name, &length); +	if (!prop) { +		debug("%s: could not find property %s\n", +		      fdt_get_name(blob, node, NULL), name); +		return length; +	} + +	if (length == sizeof(u32)) { +		result->typ = fdtdec_get_int(blob, node, name, 0); +		result->min = result->typ; +		result->max = result->typ; +	} else { +		ret = fdtdec_get_int_array(blob, node, name, &result->min, 3); +	} + +	return ret; +} + +int fdtdec_decode_display_timing(const void *blob, int parent, int index, +				 struct display_timing *dt) +{ +	int i, node, timings_node; +	u32 val = 0; +	int ret = 0; + +	timings_node = fdt_subnode_offset(blob, parent, "display-timings"); +	if (timings_node < 0) +		return timings_node; + +	for (i = 0, node = fdt_first_subnode(blob, timings_node); +	     node > 0 && i != index; +	     node = fdt_next_subnode(blob, node)) +		i++; + +	if (node < 0) +		return node; + +	memset(dt, 0, sizeof(*dt)); + +	ret |= decode_timing_property(blob, node, "hback-porch", +				      &dt->hback_porch); +	ret |= decode_timing_property(blob, node, "hfront-porch", +				      &dt->hfront_porch); +	ret |= decode_timing_property(blob, node, "hactive", &dt->hactive); +	ret |= decode_timing_property(blob, node, "hsync-len", &dt->hsync_len); +	ret |= decode_timing_property(blob, node, "vback-porch", +				      &dt->vback_porch); +	ret |= decode_timing_property(blob, node, "vfront-porch", +				      &dt->vfront_porch); +	ret |= decode_timing_property(blob, node, "vactive", &dt->vactive); +	ret |= decode_timing_property(blob, node, "vsync-len", &dt->vsync_len); +	ret |= decode_timing_property(blob, node, "clock-frequency", +				      &dt->pixelclock); + +	dt->flags = 0; +	val = fdtdec_get_int(blob, node, "vsync-active", -1); +	if (val != -1) { +		dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH : +				DISPLAY_FLAGS_VSYNC_LOW; +	} +	val = fdtdec_get_int(blob, node, "hsync-active", -1); +	if (val != -1) { +		dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH : +				DISPLAY_FLAGS_HSYNC_LOW; +	} +	val = fdtdec_get_int(blob, node, "de-active", -1); +	if (val != -1) { +		dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH : +				DISPLAY_FLAGS_DE_LOW; +	} +	val = fdtdec_get_int(blob, node, "pixelclk-active", -1); +	if (val != -1) { +		dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : +				DISPLAY_FLAGS_PIXDATA_NEGEDGE; +	} + +	if (fdtdec_get_bool(blob, node, "interlaced")) +		dt->flags |= DISPLAY_FLAGS_INTERLACED; +	if (fdtdec_get_bool(blob, node, "doublescan")) +		dt->flags |= DISPLAY_FLAGS_DOUBLESCAN; +	if (fdtdec_get_bool(blob, node, "doubleclk")) +		dt->flags |= DISPLAY_FLAGS_DOUBLECLK; + +	return 0; +} +  int fdtdec_setup(void)  {  #ifdef CONFIG_OF_CONTROL | 
