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

Bob Paauwe bob.j.paauwe at intel.com
Tue Feb 24 09:41:41 PST 2015


On Tue, 24 Feb 2015 17:17:18 +0100
Daniel Vetter <daniel at ffwll.ch> wrote:

> 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.

For drm properties, the idea was to expand the existing hard coded
default values with configurable defaults.  For the pre-atomic
connector properties, when the property instance was created, they were
created with a specific default value.  

I haven't looked closely at the atomic property sets yet to see if this
interface also makes sense with them, but that is on my near-term todo
list.  Most of this code had been developed prior to the atomic patches.

> 
> 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.

Yes, I believe it will map easily also, and plan to look at this next. 

> 
> 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.

ACPI isn't really driver agnostic since it's only available to IA based
drivers. So I'm not sure I follow your thinking here.  Maybe it will
make more sense to me as I look at the atomic properties. 

I needed to get some fresh eyes looking at this which is why I posted
it. I appreciate the feedback and will be incorporating it into the
next version.

> 
> 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
> 



More information about the Intel-gfx mailing list