[Intel-gfx] [RFC 01/12] drm/i915/config: Initial framework

Daniel Vetter daniel at ffwll.ch
Tue Feb 24 08:17:18 PST 2015


On Thu, Feb 12, 2015 at 03:41:27PM -0800, Bob Paauwe wrote:
> This adds an init-time configuration framework that parses configuration
> data from an ACPI property table. The table is assumed to have well
> defined sub-device property tables that correspond to the various
> driver components.  Initially the following sub-device tables are
> defined:
> 
> CRTC (CRTC)
>    The CRTC sub-device table contains additional sub-device tables
>    where each one corresponds to a CRTC.  Each CRTC sub-device must
>    include a property called "id" whose value matches the driver's
>    crtc id. Additional properties for the CRTC are used to configure
>    the crtc.
> 
> Connector (CNCT)
>    The CNCT sub-device table contains additional sub-device tables
>    where each one corresponds to a connector. Each of the connector
>    sub-device tables must include a property called "name" whose value
>    matches a connector name assigned by the driver (see later patch
>    for output name function). Additional connector properties can
>    be set through these tables.
> 
> Plane (PLNS)
>    The PLNS sub-device table contains additional sub-device tables
>    where each one corresponds to a plane.  [this needs additional work]
> 
> In addition, the main device property table for the device may
> contain configuration information that applies to general driver
> configuration.
> 
> The framework includes a couple of helper functions to access the
> configuration data.
> 
>    intel_config_get_integer() will look up a configuration property
>    and return the integer value associated with it.
> 
>    intel_config_init_<component>_property() will look up a
>    configuration property and assign the value to a drm
>    property of the same name.  These functions are used to
>    initialize drm property instances to specific values.
> 
> Signed-off-by: Bob Paauwe <bob.j.paauwe at intel.com>

Like Jani I'm mostly concerned about maintaining yet another slightly
different definition of paramters and settings here - we already have (or
will soon grow) per crtc/plane/connector properties for atomic.

My high-level idea for this was that we reuse the atomic support (once we
have it) and just take the acpi tables as a slightly different source for
an atomic update. Since the design of a name/value pair for objects is
very similar to what we do with the atomic ioctl this hopefully should map
fairly well.

Internally in the driver the only work needed to do would be to add any
missing properties. All the acpi atomic update code should be fully i915
agnostic and only use generic atomic update interfaces.

Would this work or do I overlook something important here.
-Daniel

> ---
>  drivers/gpu/drm/i915/Makefile       |   3 +-
>  drivers/gpu/drm/i915/i915_dma.c     |   4 +
>  drivers/gpu/drm/i915/i915_drv.h     |  16 ++
>  drivers/gpu/drm/i915/i915_params.c  |   6 +
>  drivers/gpu/drm/i915/intel_config.c | 542 ++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h    |  28 ++
>  6 files changed, 598 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/i915/intel_config.c
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index f025e7f..462de19 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -12,7 +12,8 @@ i915-y := i915_drv.o \
>            i915_suspend.o \
>  	  i915_sysfs.o \
>  	  intel_pm.o \
> -	  intel_runtime_pm.o
> +	  intel_runtime_pm.o \
> +	  intel_config.o
>  
>  i915-$(CONFIG_COMPAT)   += i915_ioc32.o
>  i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 5804aa5..9501360 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -656,6 +656,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  	dev->dev_private = dev_priv;
>  	dev_priv->dev = dev;
>  
> +	intel_config_init(dev);
> +
>  	/* Setup the write-once "constant" device info */
>  	device_info = (struct intel_device_info *)&dev_priv->info;
>  	memcpy(device_info, info, sizeof(dev_priv->info));
> @@ -929,6 +931,8 @@ int i915_driver_unload(struct drm_device *dev)
>  
>  	acpi_video_unregister();
>  
> +	intel_config_shutdown(dev);
> +
>  	if (drm_core_check_feature(dev, DRIVER_MODESET))
>  		intel_fbdev_fini(dev);
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 2dedd43..165091c 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1645,6 +1645,20 @@ struct i915_virtual_gpu {
>  	bool active;
>  };
>  
> +struct intel_config_node {
> +	struct acpi_device *adev;
> +	struct list_head node;
> +	struct list_head list;
> +};
> +
> +struct intel_config_info {
> +	struct intel_config_node base;
> +	struct list_head crtc_list;
> +	struct list_head connector_list;
> +	struct list_head plane_list;
> +};
> +
> +
>  struct drm_i915_private {
>  	struct drm_device *dev;
>  	struct kmem_cache *slab;
> @@ -1886,6 +1900,7 @@ struct drm_i915_private {
>  	u32 long_hpd_port_mask;
>  	u32 short_hpd_port_mask;
>  	struct work_struct dig_port_work;
> +	struct intel_config_info *config_info;
>  
>  	/*
>  	 * if we get a HPD irq from DP and a HPD irq from non-DP
> @@ -2528,6 +2543,7 @@ struct i915_params {
>  	int enable_ips;
>  	int invert_brightness;
>  	int enable_cmd_parser;
> +	char cfg_firmware[PATH_MAX];
>  	/* leave bools at the end to not create holes */
>  	bool enable_hangcheck;
>  	bool fastboot;
> diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
> index 44f2262..f92621c 100644
> --- a/drivers/gpu/drm/i915/i915_params.c
> +++ b/drivers/gpu/drm/i915/i915_params.c
> @@ -53,6 +53,7 @@ struct i915_params i915 __read_mostly = {
>  	.mmio_debug = 0,
>  	.verbose_state_checks = 1,
>  	.nuclear_pageflip = 0,
> +	.cfg_firmware = "",
>  };
>  
>  module_param_named(modeset, i915.modeset, int, 0400);
> @@ -183,3 +184,8 @@ MODULE_PARM_DESC(verbose_state_checks,
>  module_param_named_unsafe(nuclear_pageflip, i915.nuclear_pageflip, bool, 0600);
>  MODULE_PARM_DESC(nuclear_pageflip,
>  		 "Force atomic modeset functionality; only planes work for now (default: false).");
> +
> +module_param_string(cfg_firmware, i915.cfg_firmware, sizeof(i915.cfg_firmware), 0444);
> +MODULE_PARM_DESC(cfg_firmware,
> +		 "Load configuration firmware from built-in data or /lib/firmware. ");
> +
> diff --git a/drivers/gpu/drm/i915/intel_config.c b/drivers/gpu/drm/i915/intel_config.c
> new file mode 100644
> index 0000000..cf7da93
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_config.c
> @@ -0,0 +1,542 @@
> +/*
> + * i915 configuration via ACPI device properties.
> + *
> + * Copyright (C) 2014, 2015 Intel Corporation
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and its
> + * documentation for any purpose is hereby granted without fee, provided that
> + * the above copyright notice appear in all copies and that both that copyright
> + * notice and this permission notice appear in supporting documentation, and
> + * that the name of the copyright holders not be used in advertising or
> + * publicity pertaining to distribution of the software without specific,
> + * written prior permission.  The copyright holders make no representations
> + * about the suitability of this software for any purpose.  It is provided "as
> + * is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> + * OF THIS SOFTWARE.
> + */
> +#include <linux/acpi.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/firmware.h>
> +#include <linux/ctype.h>
> +#include <acpi/acpi_bus.h>
> +#include "intel_drv.h"
> +#include <drm/i915_drm.h>
> +#include "i915_drv.h"
> +#include "i915_trace.h"
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +
> +
> +#define i915_ACPI_PRP_ROOT "\\_SB.PRP.GFX0"
> +
> +/*
> + * Load an ACPI property table into the ACPI subsystem.
> + *
> + * First, verify that a table isn't already loaded.  The table may
> + * be part of the ACPI firmware and thus loaded by the ACPI sub-system
> + * during boot.  It is also possible for ACPI sub-system to load tables
> + * to override those supplied by the firmware.
> + *
> + * If a property table for the GFX device has not been loaded, attempt
> + * to load one from /lib/firmware here.  The name will default to
> + * drm_i915.aml but the name be overridden by the cfg_firmware module
> + * parameter.
> + *
> + * The order of precidence for table loading is:
> + *   - dyanamic table loaded by ACPI driver
> + *   - table built into firmware
> + *   - dynamic table loaded based on driver name or module parameter
> + *
> + * If the table is loaded by the driver, it will be unloaded when the
> + * driver module is unloaded.  Tables that are part of the firmware or
> + * overridden by the ACPI driver are not unloaded and cannot be replaced
> + * by tables loaded by the driver.
> + */
> +static int intel_acpi_load_table(struct drm_device *dev, char *firmware)
> +{
> +	struct acpi_table_header *table;
> +	acpi_status status;
> +	acpi_handle handle;
> +	struct acpi_device *acpi_dev = NULL;
> +	const struct firmware *fw;
> +	int ret = 0;
> +
> +	/* make sure the table isn't already loaded before loading it */
> +	status = acpi_get_handle(ACPI_ROOT_OBJECT, i915_ACPI_PRP_ROOT, &handle);
> +	if (ACPI_FAILURE(status)) {
> +
> +		/* Try to dynamically load a table.... */
> +		DRM_DEBUG_DRIVER("Requesting configuration table: %s\n",
> +				 firmware);
> +		ret = request_firmware(&fw, firmware, dev->dev);
> +		if (ret != 0) {
> +			DRM_ERROR("Failed to find ACPI table %s: %d\n",
> +				  firmware, ret);
> +			fw = NULL;
> +			goto bad_table;
> +		} else {
> +			table = (struct acpi_table_header *)fw->data;
> +		}
> +
> +		/* Load the table into the acpi device. */
> +		status = acpi_load_table(table);
> +		if (ACPI_FAILURE(status))
> +			goto bad_table;
> +
> +		add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, true);
> +
> +		/* Get a handle and scan the bus */
> +		status = acpi_get_handle(ACPI_ROOT_OBJECT, i915_ACPI_PRP_ROOT,
> +					 &handle);
> +		acpi_bus_scan(handle);
> +
> +		if (acpi_bus_get_device(handle, &acpi_dev))
> +			goto bad_table;
> +
> +		acpi_bind_one(dev->dev, acpi_dev);
> +
> +	} else {
> +		DRM_DEBUG_DRIVER("ACPI Property table previously loaded for _SB.PRP.GFX0\n");
> +	}
> +
> +	return 0;
> +
> +bad_table:
> +	release_firmware(fw);
> +	return -ENODEV;
> +}
> +
> +/*
> + * Use ACPI methods to get the property.
> + *
> + * This isn't using the generic device_property_read because that
> + * can only access properties associated with the actual device. It
> + * doesn't understand our sub-component property tree.
> + */
> +static bool node_property(struct intel_config_node *n,
> +			  const char *prop,
> +			  void *value)
> +{
> +	int ret = 0;
> +	const union acpi_object *obj;
> +
> +	ret = acpi_dev_get_property(n->adev, prop, ACPI_TYPE_ANY, &obj);
> +	if (ret == -ENODATA) {
> +		/*
> +		 * This isn't really a failure, it's ok if the property
> +		 * doesn't exist. The message is for debug purposes only.
> +		 */
> +		DRM_DEBUG_DRIVER("Property \"%s\" not found in %s\n",
> +				 prop, acpi_device_bid(n->adev));
> +	} else if (ret == -EINVAL) {
> +		DRM_ERROR("Invalid acpi device or property name.\n");
> +	} else if (ret) {
> +		/* This is a failure. */
> +		DRM_ERROR("Property request failed for %s: %d\n", prop, ret);
> +	} else {
> +		switch (obj->type) {
> +		case ACPI_TYPE_INTEGER:
> +			*(u32 *)value = obj->integer.value;
> +			break;
> +		case ACPI_TYPE_STRING:
> +			*(char **)value = obj->string.pointer;
> +			break;
> +		default:
> +			DRM_ERROR("Unsupported property type, only support integer and string.\n");
> +			ret = -1;
> +			break;
> +		}
> +	}
> +
> +	return ret == 0;
> +}
> +
> +
> +/**
> + * intel_config_init -
> + *
> + * Initialize the configuration framework by attempting to load a
> + * property table and parse the contents into component lists.
> + *
> + * @dev: The drm driver device.
> + */
> +void intel_config_init(struct drm_device *dev)
> +{
> +	struct intel_config_info *info;
> +	struct intel_config_node *new_node, *tmp;
> +	acpi_handle handle;
> +	struct acpi_device *cl, *component;
> +	char *cname;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	/* Load an ACPI table from /lib/firmware.  */
> +	snprintf(i915.cfg_firmware, PATH_MAX, "drm_%s.aml", dev->driver->name);
> +
> +	if (intel_acpi_load_table(dev, i915.cfg_firmware) != 0) {
> +		DRM_ERROR("Failed to load ACPI device property table.\n");
> +		return;
> +	}
> +
> +	DRM_DEBUG_DRIVER("Loaded ACPI configuration for %s\n",
> +			 dev->driver->name);
> +
> +	info = kzalloc(sizeof(*info), GFP_KERNEL);
> +	if (!info) {
> +		DRM_ERROR("Failed to allocate memory for configuration.\n");
> +		return;
> +	}
> +
> +	INIT_LIST_HEAD(&info->base.list);
> +	INIT_LIST_HEAD(&info->crtc_list);
> +	INIT_LIST_HEAD(&info->connector_list);
> +	INIT_LIST_HEAD(&info->plane_list);
> +
> +	handle = ACPI_HANDLE(dev->dev);
> +	if (!handle) {
> +		DRM_DEBUG_DRIVER("No associated ACPI handle.\n");
> +		kfree(info);
> +		return;
> +	} else {
> +		acpi_bus_get_device(handle, &info->base.adev);
> +	}
> +
> +	/*
> +	 * Create a list of one for the top level driver config.
> +	 *
> +	 * We don't really need a full config_info structure for this but
> +	 * it simplifies the handling of driver general config settings
> +	 * as we don't have to have a special case and unique structure
> +	 * just for this.
> +	 */
> +	INIT_LIST_HEAD(&info->base.node);
> +	list_add_tail(&info->base.node, &info->base.list);
> +
> +/* Component sub-device ACPI names */
> +#define i915_COMPONENT_CRTC "CRTC"
> +#define i915_COMPONENT_CONNECTOR "CNCT"
> +#define i915_COMPONENT_PLANE "PLNS"
> +
> +	/* Build lists */
> +	list_for_each_entry(component, &info->base.adev->children, node) {
> +		if (!component)
> +			continue;
> +
> +		cname = acpi_device_bid(component);
> +
> +		list_for_each_entry(cl, &component->children, node) {
> +			new_node = kzalloc(sizeof(*new_node), GFP_KERNEL);
> +			if (!new_node)
> +				goto bail;
> +			new_node->adev = cl;
> +			INIT_LIST_HEAD(&new_node->node);
> +
> +			/* Add to the appropriate list */
> +			if (strcmp(cname, i915_COMPONENT_CRTC) == 0) {
> +				list_add_tail(&new_node->node,
> +					      &info->crtc_list);
> +			} else if (strcmp(cname, i915_COMPONENT_CONNECTOR) == 0) {
> +				list_add_tail(&new_node->node,
> +					      &info->connector_list);
> +			} else if (strcmp(cname, i915_COMPONENT_PLANE) == 0) {
> +				list_add_tail(&new_node->node,
> +					      &info->plane_list);
> +			} else {
> +				/* unknown component, ignore it */
> +				kfree(new_node);
> +			}
> +		}
> +	}
> +
> +	dev_priv->config_info = info;
> +	DRM_DEBUG_DRIVER("i915 Configuration loaded.\n");
> +	return;
> +
> +bail:
> +	DRM_DEBUG_DRIVER("i915 Configuration aborted, insufficient memory.\n");
> +	list_for_each_entry_safe(new_node, tmp, &info->crtc_list, node)
> +		kfree(new_node);
> +	list_for_each_entry_safe(new_node, tmp, &info->connector_list, node)
> +		kfree(new_node);
> +	list_for_each_entry_safe(new_node, tmp, &info->plane_list, node)
> +		kfree(new_node);
> +
> +	kfree(info);
> +	dev_priv->config_info = NULL;
> +}
> +
> +
> +/**
> + * Clean up the configuration infrastructure as the driver is
> + * shuting down.  Don't leak memory!
> + *
> + * @dev: The drm driver device.
> + */
> +void intel_config_shutdown(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	acpi_handle handle;
> +	acpi_status status;
> +	struct acpi_device *adev;
> +	struct intel_config_info *info;
> +	struct intel_config_node *n, *tmp;
> +
> +	if (dev_priv->config_info == NULL)
> +		return;
> +
> +	/* Free the component lists.  */
> +	info = dev_priv->config_info;
> +	list_for_each_entry_safe(n, tmp, &info->crtc_list, node)
> +		kfree(n);
> +	list_for_each_entry_safe(n, tmp, &info->connector_list, node)
> +		kfree(n);
> +	list_for_each_entry_safe(n, tmp, &info->plane_list, node)
> +		kfree(n);
> +
> +	/* Unload any dynamically loaded ACPI property table */
> +	handle = ACPI_HANDLE(dev->dev);
> +
> +	DRM_DEBUG_DRIVER("Unloading dynamic i915 Configuration ACPI table.\n");
> +	if (handle) {
> +
> +		acpi_unbind_one(dev->dev);
> +
> +		if (acpi_bus_get_device(handle, &adev))
> +			DRM_ERROR("Failed to get ACPI bus device.\n");
> +		else
> +			acpi_bus_trim(adev);
> +
> +		status = acpi_unload_parent_table(handle);
> +		if (ACPI_FAILURE(status))
> +			DRM_ERROR("Failed to unload the i915 Configuration"
> +				  "ACPI table. %d\n", status);
> +	}
> +}
> +
> +
> +
> +/*
> + * does_name_match
> + *
> + * The various drm components have names assocated with them. To link
> + * a component in the ACPI property tree, use a "special" property
> + * called "name".
> + *
> + * The exception is the general driver properties.  There is no "name"
> + * property associated with those.  We could force one, but that may
> + * be less intuitive than leaving the name empty.
> + *
> + * This function look for a property called "name" and compares the
> + * value of that property with the passed in name parameter.
> + */
> +static bool does_name_match(struct intel_config_node *node, const char *name)
> +{
> +	char *p_name;
> +
> +	/*
> +	 * General driver properties aren't in a section with a "name"
> +	 * property. Thus this should just return true in that case.
> +	 */
> +	if (!name || strlen(name) == 0)
> +		return true;
> +
> +
> +	/* Look up a name property and see if it matches */
> +	if (node_property(node, "name", &p_name)) {
> +		if (strcmp(name, p_name) == 0)
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +
> +/*
> + * Map the configuration sub component enum to the cached
> + * sub component list.
> + */
> +static struct list_head *cfg_type_to_list(struct intel_config_info *info,
> +					  enum cfg_type cfg_type)
> +{
> +	switch (cfg_type) {
> +	case CFG_DRV:
> +		return &info->base.list;
> +	case CFG_CRTC:
> +		return &info->crtc_list;
> +	case CFG_CONNECTOR:
> +		return &info->connector_list;
> +	case CFG_PLANE:
> +		return &info->plane_list;
> +	}
> +	return NULL;
> +}
> +
> +/*
> + * Integer property.
> + *
> + * Look up a property and set the value pointer to the property value.
> + *
> + * returns true if the property was found, false if not.
> + */
> +bool intel_config_get_integer(struct drm_i915_private *dev_priv,
> +			      enum cfg_type cfg_type,
> +			      const char *name,
> +			      const char *property,
> +			      uint32_t *value)
> +{
> +	struct intel_config_info *info = dev_priv->config_info;
> +	struct intel_config_node *n;
> +	struct list_head *list;
> +	bool ret = false;
> +
> +	if (!info)
> +		return false;
> +
> +	list = cfg_type_to_list(info, cfg_type);
> +	if (!list)
> +		return false;
> +
> +	list_for_each_entry(n, list, node) {
> +		if (does_name_match(n, name)) {
> +			if (node_property(n, property, value))
> +				return true;
> +		}
> +	}
> +
> +	return false;
> +}
> +
> +/*
> + * Look up a drm property name in the configuration store and if
> + * found, return the value.
> + *
> + * A default value is included in the parameter list so that something
> + * reasonable is returned if the lookup fails to find a matching
> + * configuration key.
> + */
> +static uint64_t lookup_property(struct drm_i915_private *dev_priv,
> +				const char *name,
> +				struct drm_property *property,
> +				enum cfg_type cfg_type,
> +				uint64_t dflt)
> +{
> +	struct intel_config_info *info = dev_priv->config_info;
> +	struct drm_property_enum *prop_enum;
> +	const char *value;
> +	uint64_t retval = dflt;
> +	struct intel_config_node *n;
> +	struct list_head *list;
> +
> +	list = cfg_type_to_list(info, cfg_type);
> +	if (!list)
> +		goto out;
> +
> +	list_for_each_entry(n, list, node) {
> +		if (!does_name_match(n, name))
> +			continue;
> +		/*
> +		 * FIXME: This is assuming that the type is string
> +		 * for enun drm properties.  This should be more
> +		 * generic and map drm property types to ACPI property
> +		 * types.
> +		 */
> +		if (!node_property(n, property->name, &value))
> +			continue;
> +
> +		/* Look for a matching enum */
> +		list_for_each_entry(prop_enum, &property->enum_list, head) {
> +			if (strcmp(value, prop_enum->name) == 0) {
> +				retval = prop_enum->value;
> +				goto out;
> +			}
> +		}
> +	}
> +
> +out:
> +	return retval;
> +}
> +
> +/*
> + * Connector properties.
> + *
> + * If a connector drm property has a corresponding configuration property,
> + * use the configuration property value to initialize the drm property.
> + */
> +uint64_t intel_config_init_connector_property(struct drm_connector *connector,
> +					      const char *name,
> +					      struct drm_property *property,
> +					      uint64_t dflt)
> +{
> +	struct drm_i915_private *dev_priv = connector->dev->dev_private;
> +	struct intel_config_info *info = dev_priv->config_info;
> +	uint64_t retval;
> +
> +	if (!info)
> +		goto out;
> +
> +	retval = lookup_property(dev_priv, name, property, CFG_CONNECTOR, dflt);
> +
> +out:
> +	drm_object_attach_property(&connector->base, property, retval);
> +	return retval;
> +}
> +
> +
> +/*
> + * Plane properties.
> + *
> + * If a plane drm property has a corresponding configuration property,
> + * use the configuration property value to initialize the drm property.
> + */
> +uint64_t intel_config_init_plane_property(struct drm_plane *plane,
> +					  const char *name,
> +					  struct drm_property *property,
> +					  uint64_t dflt)
> +{
> +	struct drm_i915_private *dev_priv = plane->dev->dev_private;
> +	struct intel_config_info *info = dev_priv->config_info;
> +	uint64_t retval;
> +
> +	if (!info)
> +		goto out;
> +
> +	retval = lookup_property(dev_priv, name, property, CFG_PLANE, dflt);
> +
> +out:
> +	drm_object_attach_property(&plane->base, property, retval);
> +	return retval;
> +}
> +
> +
> +/*
> + * CRTC properties.
> + *
> + * If a crtc drm property has a corresponding configuration property,
> + * use the configuration property value to initialize the drm property.
> + */
> +uint64_t intel_config_init_crtc_property(struct drm_crtc *crtc,
> +					 const char *name,
> +					 struct drm_property *property,
> +					 uint64_t dflt)
> +{
> +	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
> +	struct intel_config_info *info = dev_priv->config_info;
> +	uint64_t retval;
> +
> +	if (!info)
> +		goto out;
> +
> +	retval = lookup_property(dev_priv, name, property, CFG_CRTC, dflt);
> +
> +out:
> +	drm_object_attach_property(&crtc->base, property, retval);
> +	return retval;
> +}
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 1de8e20..aefd95e 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1259,4 +1259,32 @@ void intel_plane_destroy_state(struct drm_plane *plane,
>  			       struct drm_plane_state *state);
>  extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
>  
> +/* intel_config.c */
> +enum cfg_type {
> +	CFG_DRV,
> +	CFG_CRTC,
> +	CFG_CONNECTOR,
> +	CFG_PLANE
> +};
> +
> +void intel_config_init(struct drm_device *dev);
> +void intel_config_shutdown(struct drm_device *dev);
> +bool intel_config_get_integer(struct drm_i915_private *dev_priv,
> +			  enum cfg_type cfg_type,
> +			  const char *name,
> +			  const char *property,
> +			  uint32_t *value);
> +uint64_t intel_config_init_connector_property(struct drm_connector *connector,
> +			  const char *name,
> +			  struct drm_property *property,
> +			  uint64_t dflt);
> +uint64_t intel_config_init_plane_property(struct drm_plane *plane,
> +			  const char *name,
> +			  struct drm_property *property,
> +			  uint64_t dflt);
> +uint64_t intel_config_init_crtc_property(struct drm_crtc *crtc,
> +			  const char *name,
> +			  struct drm_property *property,
> +			  uint64_t dflt);
> +
>  #endif /* __INTEL_DRV_H__ */
> -- 
> 2.1.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch


More information about the Intel-gfx mailing list