All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 00/12] i915 init-time configuration.
@ 2015-02-12 23:41 Bob Paauwe
  2015-02-12 23:41 ` [RFC 01/12] drm/i915/config: Initial framework Bob Paauwe
                   ` (12 more replies)
  0 siblings, 13 replies; 32+ messages in thread
From: Bob Paauwe @ 2015-02-12 23:41 UTC (permalink / raw)
  To: intel-gfx

Background:

This capability is targeted at deeply embedded appliance like devices
that make use of Intel integrated graphics.  There are a few use cases
that are not currently supported by the i915 driver.  For example,
they may not be running userspace code that is capable of querying and
setting the various DRM properties and would like them set during the
driver initialization. Also they may be using a custom firmware bootloader
that does not include any graphics initialization or VBT information.  

This level of initialization configuration has been available in
the Intel EMGD kernel driver and a similar level of configurability will
be expected as designs transition to the i915 driver.

This patch set provides a framework that makes use of ACPI property
tables containing configuration information.  It also includes some
examples on how this may be applied to various aspects of the i915
driver initialization.

Series description:

Patch 1 creates the initial framework. It looks up a specific ACPI
property table and builds lists containing the configuration found
in that table.  It includes functions that can make use of that 
configuration information.

Patch 2 adds a function to i915 that provides a unique name for
each output.  We previously had something similar to this in the
driver for debug output, it was not be used and removed recently.

Patch 3 is the first example usage.  We check the configuration for
a CRTC bits-per-pixel value and use that if EDID does not provide
this.

Patch 4 is an example of using the configuration to specify a 
default value for the DP panel fitter property.

Patch 5 is an example of using the configuration to specify default
values for a couple of common connector properties.

Patch 6 modifies the framework slightly to better support the 
remaining examples.

Patch 7 adds a function to the framework that looks for a 
workaround section. If found, it builds a list of workarounds that
can be used in place of of the workarounds hardcoded in the driver.

Patch 8 changes the workaround initialization code to make use
of the workaround list from the configuration instead of the
built-in workaround list.

Patch 9 adds functions to the frame work that look for a VBT
section and parse that information into the driver's VBT structures.

Patch 10 adds an example/test ACPI property table and adds code to
the frame to build this table into the driver.  This is mainly for
testing the framework, but may also be useful for truly embedded
devices as a way to embed the configuration.

Patch 11 adds an example workaround section to the test ACPI property
table.

Patch 12 add an example VBT section to the test ACPI property table.

Bob Paauwe (12):
  drm/i915/config: Initial framework
  drm/i915/config: Introduce intel_output_name
  drm/i915/config: Add init-time configuration of bits per color.
  drm/i915/config: Set dp panel fitter property based on init-time
    config.
  drm/i915/config: Set general connector properties using config.
  drm/i915/config: Split out allocation of list nodes.
  drm/i915/config: Get workaround information from configuration.
  drm/i915/config: Use workarounds list from configuration.
  drm/i915/config: Add VBT settings configuration.
  drm/i915/config: Introduce a test table and code to make use of it.
  drm/i915/config: Add workaround properties to ACPI table.
  drm/i915/config: Add ACPI device examples for VBT configuration.

 drivers/gpu/drm/i915/Makefile            |    3 +-
 drivers/gpu/drm/i915/i915-properties.asl |  340 ++++++++++
 drivers/gpu/drm/i915/i915-properties.hex |  409 ++++++++++++
 drivers/gpu/drm/i915/i915_dma.c          |    6 +
 drivers/gpu/drm/i915/i915_drv.h          |   18 +
 drivers/gpu/drm/i915/i915_params.c       |    6 +
 drivers/gpu/drm/i915/intel_config.c      | 1002 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c     |   71 +++
 drivers/gpu/drm/i915/intel_dp.c          |    8 +-
 drivers/gpu/drm/i915/intel_drv.h         |   33 +
 drivers/gpu/drm/i915/intel_modes.c       |    8 +-
 drivers/gpu/drm/i915/intel_ringbuffer.c  |   19 +-
 12 files changed, 1909 insertions(+), 14 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/i915-properties.asl
 create mode 100644 drivers/gpu/drm/i915/i915-properties.hex
 create mode 100644 drivers/gpu/drm/i915/intel_config.c

-- 
2.1.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* [RFC 01/12] drm/i915/config: Initial framework
  2015-02-12 23:41 [RFC 00/12] i915 init-time configuration Bob Paauwe
@ 2015-02-12 23:41 ` Bob Paauwe
  2015-02-13  8:19   ` Jani Nikula
  2015-02-24 16:17   ` Daniel Vetter
  2015-02-12 23:41 ` [RFC 02/12] drm/i915/config: Introduce intel_output_name Bob Paauwe
                   ` (11 subsequent siblings)
  12 siblings, 2 replies; 32+ messages in thread
From: Bob Paauwe @ 2015-02-12 23:41 UTC (permalink / raw)
  To: intel-gfx

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@intel.com>
---
 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@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [RFC 02/12] drm/i915/config: Introduce intel_output_name
  2015-02-12 23:41 [RFC 00/12] i915 init-time configuration Bob Paauwe
  2015-02-12 23:41 ` [RFC 01/12] drm/i915/config: Initial framework Bob Paauwe
@ 2015-02-12 23:41 ` Bob Paauwe
  2015-02-13  8:12   ` Jani Nikula
  2015-02-12 23:41 ` [RFC 03/12] drm/i915/config: Add init-time configuration of bits per color Bob Paauwe
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 32+ messages in thread
From: Bob Paauwe @ 2015-02-12 23:41 UTC (permalink / raw)
  To: intel-gfx

Human readable name for each output type to correspond with names
used in the ACPI property tables.

Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 57 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |  1 +
 2 files changed, 58 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3b0fe9f..de6de83 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12440,6 +12440,63 @@ static bool intel_crt_present(struct drm_device *dev)
 	return true;
 }
 
+/*
+ * Provide a name for the various outputs.
+ */
+const char *intel_output_name(struct intel_connector *connector)
+{
+	int output;
+	static const char *names[] = {
+		[INTEL_OUTPUT_UNUSED] = "Unused",
+		[INTEL_OUTPUT_ANALOG] = "Analog",
+		[INTEL_OUTPUT_DVO] = "DVO",
+		[INTEL_OUTPUT_SDVO] = "SDVO",
+		[INTEL_OUTPUT_LVDS] = "LVDS",
+		[INTEL_OUTPUT_TVOUT] = "TV",
+		[INTEL_OUTPUT_HDMI] = "HDMI",
+		[INTEL_OUTPUT_DISPLAYPORT] = "DisplayPort",
+		[INTEL_OUTPUT_EDP] = "eDP",
+		[INTEL_OUTPUT_DSI] = "DSI",
+		[INTEL_OUTPUT_UNKNOWN] = "Unknown",
+	};
+	static const char *name_ex[] = {
+		[0] = "HDMI_A",
+		[1] = "HDMI_B",
+		[2] = "HDMI_C",
+		[3] = "HDMI_D",
+		[4] = "DisplayPort_A",
+		[5] = "DisplayPort_B",
+		[6] = "DisplayPort_C",
+		[7] = "DisplayPort_D",
+		[8] = "eDP_A",
+		[9] = "eDP_B",
+		[10] = "eDP_C",
+		[11] = "eDP_D",
+	};
+
+	if (!connector || !connector->encoder)
+		return "Unknown";
+
+	switch (connector->encoder->type) {
+	case INTEL_OUTPUT_HDMI:
+	case INTEL_OUTPUT_DISPLAYPORT:
+	case INTEL_OUTPUT_EDP:
+		output = ((connector->encoder->type - INTEL_OUTPUT_HDMI) * 4) +
+			enc_to_dig_port(&connector->encoder->base)->port;
+
+		if (output < 0 || output >= ARRAY_SIZE(name_ex))
+			return "Invalid";
+
+		return name_ex[output];
+	default:
+		if (output < 0 || output >= ARRAY_SIZE(names) || !names[output])
+			return "Invalid";
+
+		return names[output];
+	}
+}
+
+
 static void intel_setup_outputs(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index aefd95e..4c81ee9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -893,6 +893,7 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
 
 /* intel_display.c */
 extern const struct drm_plane_funcs intel_plane_funcs;
+const char *intel_output_name(struct intel_connector *intel_connector);
 bool intel_has_pending_fb_unpin(struct drm_device *dev);
 int intel_pch_rawclk(struct drm_device *dev);
 void intel_mark_busy(struct drm_device *dev);
-- 
2.1.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [RFC 03/12] drm/i915/config: Add init-time configuration of bits per color.
  2015-02-12 23:41 [RFC 00/12] i915 init-time configuration Bob Paauwe
  2015-02-12 23:41 ` [RFC 01/12] drm/i915/config: Initial framework Bob Paauwe
  2015-02-12 23:41 ` [RFC 02/12] drm/i915/config: Introduce intel_output_name Bob Paauwe
@ 2015-02-12 23:41 ` Bob Paauwe
  2015-02-12 23:41 ` [RFC 04/12] drm/i915/config: Set dp panel fitter property based on init-time config Bob Paauwe
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 32+ messages in thread
From: Bob Paauwe @ 2015-02-12 23:41 UTC (permalink / raw)
  To: intel-gfx

Allow the init-time configuration to specify the bits per color value
that gets used if bits per color is not present in EDID data (or if EDID
is not present).

Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index de6de83..347dbad 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9957,6 +9957,20 @@ connected_sink_compute_bpp(struct intel_connector *connector,
 		connector->base.base.id,
 		connector->base.name);
 
+	/* If !bpc then see if one was specified in the static configuation */
+	if (connector->base.display_info.bpc == 0) {
+		/*
+		 * This is making the assumption that the static configuration
+		 * will use the names defined in the intel_output_name()
+		 * function to identify the output.
+		 */
+		intel_config_get_integer(to_i915(connector->base.dev),
+					CFG_CONNECTOR,
+					intel_output_name(connector),
+					"bits_per_color",
+					&connector->base.display_info.bpc);
+	}
+
 	/* Don't use an invalid EDID bpc value */
 	if (connector->base.display_info.bpc &&
 	    connector->base.display_info.bpc * 3 < bpp) {
-- 
2.1.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [RFC 04/12] drm/i915/config: Set dp panel fitter property based on init-time config.
  2015-02-12 23:41 [RFC 00/12] i915 init-time configuration Bob Paauwe
                   ` (2 preceding siblings ...)
  2015-02-12 23:41 ` [RFC 03/12] drm/i915/config: Add init-time configuration of bits per color Bob Paauwe
@ 2015-02-12 23:41 ` Bob Paauwe
  2015-02-12 23:41 ` [RFC 05/12] drm/i915/config: Set general connector properties using config Bob Paauwe
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 32+ messages in thread
From: Bob Paauwe @ 2015-02-12 23:41 UTC (permalink / raw)
  To: intel-gfx

Use the init-time configuration setting for scaling_mode to set the
initial value of the scaling_mode connector property.

Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 868a07b..2f97bea 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -4545,6 +4545,7 @@ void
 intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector)
 {
 	struct intel_connector *intel_connector = to_intel_connector(connector);
+	uint64_t fitting_mode;
 
 	intel_attach_force_audio_property(connector);
 	intel_attach_broadcast_rgb_property(connector);
@@ -4552,11 +4553,12 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
 
 	if (is_edp(intel_dp)) {
 		drm_mode_create_scaling_mode_property(connector->dev);
-		drm_object_attach_property(
-			&connector->base,
+		fitting_mode = intel_config_init_connector_property(
+			connector,
+			intel_output_name(intel_connector),
 			connector->dev->mode_config.scaling_mode_property,
 			DRM_MODE_SCALE_ASPECT);
-		intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
+		intel_connector->panel.fitting_mode = (int)fitting_mode;
 	}
 }
 
-- 
2.1.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [RFC 05/12] drm/i915/config: Set general connector properties using config.
  2015-02-12 23:41 [RFC 00/12] i915 init-time configuration Bob Paauwe
                   ` (3 preceding siblings ...)
  2015-02-12 23:41 ` [RFC 04/12] drm/i915/config: Set dp panel fitter property based on init-time config Bob Paauwe
@ 2015-02-12 23:41 ` Bob Paauwe
  2015-02-12 23:41 ` [RFC 06/12] drm/i915/config: Split out allocation of list nodes Bob Paauwe
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 32+ messages in thread
From: Bob Paauwe @ 2015-02-12 23:41 UTC (permalink / raw)
  To: intel-gfx

Set the initial value of the force audio and broadcast rgb properties
using property values found in the init-time configuration.

Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
---
 drivers/gpu/drm/i915/intel_modes.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
index 0e860f3..4647e0b 100644
--- a/drivers/gpu/drm/i915/intel_modes.c
+++ b/drivers/gpu/drm/i915/intel_modes.c
@@ -84,6 +84,7 @@ intel_attach_force_audio_property(struct drm_connector *connector)
 	struct drm_device *dev = connector->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_property *prop;
+	struct intel_connector *intel_connector = to_intel_connector(connector);
 
 	prop = dev_priv->force_audio_property;
 	if (prop == NULL) {
@@ -96,7 +97,8 @@ intel_attach_force_audio_property(struct drm_connector *connector)
 
 		dev_priv->force_audio_property = prop;
 	}
-	drm_object_attach_property(&connector->base, prop, 0);
+	intel_config_init_connector_property(connector,
+			intel_output_name(intel_connector), prop, 0);
 }
 
 static const struct drm_prop_enum_list broadcast_rgb_names[] = {
@@ -111,6 +113,7 @@ intel_attach_broadcast_rgb_property(struct drm_connector *connector)
 	struct drm_device *dev = connector->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_property *prop;
+	struct intel_connector *intel_connector = to_intel_connector(connector);
 
 	prop = dev_priv->broadcast_rgb_property;
 	if (prop == NULL) {
@@ -124,5 +127,6 @@ intel_attach_broadcast_rgb_property(struct drm_connector *connector)
 		dev_priv->broadcast_rgb_property = prop;
 	}
 
-	drm_object_attach_property(&connector->base, prop, 0);
+	intel_config_init_connector_property(connector,
+			intel_output_name(intel_connector), prop, 0);
 }
-- 
2.1.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [RFC 06/12] drm/i915/config: Split out allocation of list nodes.
  2015-02-12 23:41 [RFC 00/12] i915 init-time configuration Bob Paauwe
                   ` (4 preceding siblings ...)
  2015-02-12 23:41 ` [RFC 05/12] drm/i915/config: Set general connector properties using config Bob Paauwe
@ 2015-02-12 23:41 ` Bob Paauwe
  2015-02-13  8:15   ` Jani Nikula
  2015-02-12 23:41 ` [RFC 07/12] drm/i915/config: Get workaround information from configuration Bob Paauwe
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 32+ messages in thread
From: Bob Paauwe @ 2015-02-12 23:41 UTC (permalink / raw)
  To: intel-gfx

We'll reduce some duplicate code if we move the list node allocation
to its own function when we start processing future config items like
workaround or vbt information.

Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
---
 drivers/gpu/drm/i915/intel_config.c | 49 ++++++++++++++++++++++---------------
 1 file changed, 29 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_config.c b/drivers/gpu/drm/i915/intel_config.c
index cf7da93..fb495ed 100644
--- a/drivers/gpu/drm/i915/intel_config.c
+++ b/drivers/gpu/drm/i915/intel_config.c
@@ -161,6 +161,21 @@ static bool node_property(struct intel_config_node *n,
 }
 
 
+static bool alloc_new_node(struct acpi_device *cl, struct list_head *list)
+{
+	struct intel_config_node *new_node;
+
+	new_node = kzalloc(sizeof(*new_node), GFP_KERNEL);
+	if (!new_node)
+		return false;
+
+	new_node->adev = cl;
+	INIT_LIST_HEAD(&new_node->node);
+	list_add_tail(&new_node->node, list);
+
+	return true;
+}
+
 /**
  * intel_config_init -
  *
@@ -232,26 +247,20 @@ void intel_config_init(struct drm_device *dev)
 
 		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);
+		if (strcmp(cname, i915_COMPONENT_CRTC) == 0) {
+			list_for_each_entry(cl, &component->children, node) {
+				if (!alloc_new_node(cl, &info->crtc_list))
+					goto bail;
+			}
+		} else if (strcmp(cname, i915_COMPONENT_CONNECTOR) == 0) {
+			list_for_each_entry(cl, &component->children, node) {
+				if (!alloc_new_node(cl, &info->crtc_list))
+					goto bail;
+			}
+		} else if (strcmp(cname, i915_COMPONENT_PLANE) == 0) {
+			list_for_each_entry(cl, &component->children, node) {
+				if (!alloc_new_node(cl, &info->crtc_list))
+					goto bail;
 			}
 		}
 	}
-- 
2.1.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [RFC 07/12] drm/i915/config: Get workaround information from configuration.
  2015-02-12 23:41 [RFC 00/12] i915 init-time configuration Bob Paauwe
                   ` (5 preceding siblings ...)
  2015-02-12 23:41 ` [RFC 06/12] drm/i915/config: Split out allocation of list nodes Bob Paauwe
@ 2015-02-12 23:41 ` Bob Paauwe
  2015-02-24 13:51   ` Daniel Vetter
  2015-02-12 23:41 ` [RFC 08/12] drm/i915/config: Use workarounds list " Bob Paauwe
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 32+ messages in thread
From: Bob Paauwe @ 2015-02-12 23:41 UTC (permalink / raw)
  To: intel-gfx

Add ability to parse a list of workarounds from the ACPI table.
Initially, this expects all workarounds listed to be valid and
they replace the hard coded list initialized in init_workarounds_ring().

The main benefit of this is the ability to add/remove workarounds
at runtime.  It may also be useful to "adjust" the workaround
list for a new GPU prior to fixed support being available in the
driver.

Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h     |   1 +
 drivers/gpu/drm/i915/intel_config.c | 101 +++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_drv.h    |   4 +-
 3 files changed, 104 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 165091c..1580702 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1656,6 +1656,7 @@ struct intel_config_info {
 	struct list_head crtc_list;
 	struct list_head connector_list;
 	struct list_head plane_list;
+	struct list_head wa_list;
 };
 
 
diff --git a/drivers/gpu/drm/i915/intel_config.c b/drivers/gpu/drm/i915/intel_config.c
index fb495ed..ab14928 100644
--- a/drivers/gpu/drm/i915/intel_config.c
+++ b/drivers/gpu/drm/i915/intel_config.c
@@ -214,6 +214,7 @@ void intel_config_init(struct drm_device *dev)
 	INIT_LIST_HEAD(&info->crtc_list);
 	INIT_LIST_HEAD(&info->connector_list);
 	INIT_LIST_HEAD(&info->plane_list);
+	INIT_LIST_HEAD(&info->wa_list);
 
 	handle = ACPI_HANDLE(dev->dev);
 	if (!handle) {
@@ -239,6 +240,7 @@ void intel_config_init(struct drm_device *dev)
 #define i915_COMPONENT_CRTC "CRTC"
 #define i915_COMPONENT_CONNECTOR "CNCT"
 #define i915_COMPONENT_PLANE "PLNS"
+#define i915_COMPONENT_WORKAROUND "WRKS"
 
 	/* Build lists */
 	list_for_each_entry(component, &info->base.adev->children, node) {
@@ -262,6 +264,9 @@ void intel_config_init(struct drm_device *dev)
 				if (!alloc_new_node(cl, &info->crtc_list))
 					goto bail;
 			}
+		} else if (strcmp(cname, i915_COMPONENT_WORKAROUND) == 0) {
+			if (!alloc_new_node(cl, &info->wa_list))
+				goto bail;
 		}
 	}
 
@@ -277,6 +282,8 @@ bail:
 		kfree(new_node);
 	list_for_each_entry_safe(new_node, tmp, &info->plane_list, node)
 		kfree(new_node);
+	list_for_each_entry_safe(new_node, tmp, &info->wa_list, node)
+		kfree(new_node);
 
 	kfree(info);
 	dev_priv->config_info = NULL;
@@ -309,6 +316,8 @@ void intel_config_shutdown(struct drm_device *dev)
 		kfree(n);
 	list_for_each_entry_safe(n, tmp, &info->plane_list, node)
 		kfree(n);
+	list_for_each_entry_safe(n, tmp, &info->wa_list, node)
+		kfree(n);
 
 	/* Unload any dynamically loaded ACPI property table */
 	handle = ACPI_HANDLE(dev->dev);
@@ -384,6 +393,8 @@ static struct list_head *cfg_type_to_list(struct intel_config_info *info,
 		return &info->connector_list;
 	case CFG_PLANE:
 		return &info->plane_list;
+	case CFG_WORKAROUND:
+		return &info->wa_list;
 	}
 	return NULL;
 }
@@ -404,7 +415,6 @@ bool intel_config_get_integer(struct drm_i915_private *dev_priv,
 	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;
@@ -423,6 +433,95 @@ bool intel_config_get_integer(struct drm_i915_private *dev_priv,
 	return false;
 }
 
+
+/*
+ * Use ACPI methods to enumerate the items in the WA list.
+ *
+ * The list from the ACPI table is inserted into the ring_init
+ * workaround table.  This could either over-wright any hard coded
+ * table or append to an existing hard coded table. Need to understand
+ * which way would make more sense.
+ */
+bool intel_config_wa_add(struct drm_i915_private *dev_priv)
+{
+	struct intel_config_info *info = dev_priv->config_info;
+	const union acpi_object *properties;
+	const union acpi_object *prop, *name, *value;
+	struct list_head *list;
+	struct intel_config_node *n;
+	int i;
+	u32 idx;
+	bool ret = false;
+
+	list = cfg_type_to_list(info, CFG_WORKAROUND);
+	if (!list)
+		return false;
+
+	list_for_each_entry(n, list, node) {
+		properties = n->adev->data.properties;
+		if (!properties)
+			continue;
+
+		DRM_DEBUG_DRIVER("i915/config/wa: Found %d workarounds\n",
+					properties->package.count);
+
+		for (i = 0; i < properties->package.count; i++) {
+			prop = &properties->package.elements[i];
+			name = &prop->package.elements[0];
+			value = &prop->package.elements[1];
+			ret = true;
+
+			/*
+			 * Right now, it's assumed that any workarounds
+			 * listed in the table should be added to the
+			 * workaround array and applied. This could be a
+			 * bad assumption.
+			 *
+			 * Might be better if the workaround table includes
+			 * the PCI ID and check that before applying.
+			 */
+
+			if ((value->package.count >= 2) &&
+			    (value->type == ACPI_TYPE_PACKAGE)) {
+				/*
+				 * Package elements:
+				 *   0 = workaround register
+				 *   1 = register value
+				 *   2 = mask
+				 *   3 = mask enable vs disable bit (flags)
+				 */
+				idx = dev_priv->workarounds.count;
+				if (WARN_ON(idx >= I915_MAX_WA_REGS))
+					return ret;
+
+				dev_priv->workarounds.reg[idx].addr =
+					(u32)value->package.elements[0].integer.value;
+				dev_priv->workarounds.reg[idx].value =
+					(u32)value->package.elements[1].integer.value;
+
+				if ((u32)value->package.elements[3].integer.value)
+					dev_priv->workarounds.reg[idx].mask =
+						_MASKED_BIT_ENABLE(
+								(u32)value->package.elements[2].integer.value);
+				else
+					dev_priv->workarounds.reg[idx].mask =
+						_MASKED_BIT_DISABLE(
+								(u32)value->package.elements[2].integer.value);
+
+				dev_priv->workarounds.count++;
+
+				DRM_DEBUG_DRIVER("i915/config: WA %s = 0x%x, 0x%x, 0x%x\n",
+					   name->string.pointer,
+					   dev_priv->workarounds.reg[idx].addr,
+					   dev_priv->workarounds.reg[idx].value,
+					   dev_priv->workarounds.reg[idx].mask);
+			}
+		}
+	}
+
+	return ret;
+}
+
 /*
  * Look up a drm property name in the configuration store and if
  * found, return the value.
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 4c81ee9..e2b4e09 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1265,11 +1265,13 @@ enum cfg_type {
 	CFG_DRV,
 	CFG_CRTC,
 	CFG_CONNECTOR,
-	CFG_PLANE
+	CFG_PLANE,
+	CFG_WORKAROUND
 };
 
 void intel_config_init(struct drm_device *dev);
 void intel_config_shutdown(struct drm_device *dev);
+bool intel_config_wa_add(struct drm_i915_private *dev_priv);
 bool intel_config_get_integer(struct drm_i915_private *dev_priv,
 			  enum cfg_type cfg_type,
 			  const char *name,
-- 
2.1.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [RFC 08/12] drm/i915/config: Use workarounds list from configuration.
  2015-02-12 23:41 [RFC 00/12] i915 init-time configuration Bob Paauwe
                   ` (6 preceding siblings ...)
  2015-02-12 23:41 ` [RFC 07/12] drm/i915/config: Get workaround information from configuration Bob Paauwe
@ 2015-02-12 23:41 ` Bob Paauwe
  2015-02-12 23:41 ` [RFC 09/12] drm/i915/config: Add VBT settings configuration Bob Paauwe
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 32+ messages in thread
From: Bob Paauwe @ 2015-02-12 23:41 UTC (permalink / raw)
  To: intel-gfx

If there are ACPI table based workarounds for a platform, use those
instead of the built-in driver list when doing the workaround init.

Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
---
 drivers/gpu/drm/i915/intel_ringbuffer.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 2060610..6aa8908 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1014,16 +1014,19 @@ int init_workarounds_ring(struct intel_engine_cs *ring)
 
 	dev_priv->workarounds.count = 0;
 
-	if (IS_BROADWELL(dev))
-		return bdw_init_workarounds(ring);
+	if (!intel_config_wa_add(dev_priv)) {
+		if (IS_BROADWELL(dev))
+			return bdw_init_workarounds(ring);
 
-	if (IS_CHERRYVIEW(dev))
-		return chv_init_workarounds(ring);
+		if (IS_CHERRYVIEW(dev))
+			return chv_init_workarounds(ring);
+
+		if (IS_SKYLAKE(dev))
+			return skl_init_workarounds(ring);
+		else if (IS_GEN9(dev))
+			return gen9_init_workarounds(ring);
+	}
 
-	if (IS_SKYLAKE(dev))
-		return skl_init_workarounds(ring);
-	else if (IS_GEN9(dev))
-		return gen9_init_workarounds(ring);
 
 	return 0;
 }
-- 
2.1.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [RFC 09/12] drm/i915/config: Add VBT settings configuration.
  2015-02-12 23:41 [RFC 00/12] i915 init-time configuration Bob Paauwe
                   ` (7 preceding siblings ...)
  2015-02-12 23:41 ` [RFC 08/12] drm/i915/config: Use workarounds list " Bob Paauwe
@ 2015-02-12 23:41 ` Bob Paauwe
  2015-02-24 13:57   ` Daniel Vetter
  2015-02-12 23:41 ` [RFC 10/12] drm/i915/config: Introduce a test table and code to make use of it Bob Paauwe
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 32+ messages in thread
From: Bob Paauwe @ 2015-02-12 23:41 UTC (permalink / raw)
  To: intel-gfx

Add a new section with subsections to the ACPI configuration table
that mimics much of the information typically stored in the VBT/option
ROM. This allows for a way to override incorrect VBT data or to provide
the configuration if VBT is not present.  Lack of VBT is common in
embedded systems.

Any data found in the configuration tables will replace the driver's
vbt structure.

MIPI DSI configuration is not implmemnted at this time.

Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c     |   2 +
 drivers/gpu/drm/i915/i915_drv.h     |   1 +
 drivers/gpu/drm/i915/intel_config.c | 334 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h    |   4 +-
 4 files changed, 340 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 9501360..9119e9b 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -852,6 +852,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	if (intel_vgpu_active(dev))
 		I915_WRITE(vgtif_reg(display_ready), VGT_DRV_DISPLAY_READY);
 
+	intel_config_vbt(dev_priv);
+
 	i915_setup_sysfs(dev);
 
 	if (INTEL_INFO(dev)->num_pipes) {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 1580702..a60511e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1657,6 +1657,7 @@ struct intel_config_info {
 	struct list_head connector_list;
 	struct list_head plane_list;
 	struct list_head wa_list;
+	struct list_head vbt_list;
 };
 
 
diff --git a/drivers/gpu/drm/i915/intel_config.c b/drivers/gpu/drm/i915/intel_config.c
index ab14928..c1b06b7 100644
--- a/drivers/gpu/drm/i915/intel_config.c
+++ b/drivers/gpu/drm/i915/intel_config.c
@@ -215,6 +215,7 @@ void intel_config_init(struct drm_device *dev)
 	INIT_LIST_HEAD(&info->connector_list);
 	INIT_LIST_HEAD(&info->plane_list);
 	INIT_LIST_HEAD(&info->wa_list);
+	INIT_LIST_HEAD(&info->vbt_list);
 
 	handle = ACPI_HANDLE(dev->dev);
 	if (!handle) {
@@ -241,6 +242,7 @@ void intel_config_init(struct drm_device *dev)
 #define i915_COMPONENT_CONNECTOR "CNCT"
 #define i915_COMPONENT_PLANE "PLNS"
 #define i915_COMPONENT_WORKAROUND "WRKS"
+#define i915_COMPONENT_VBIOSTABLE "VBT"
 
 	/* Build lists */
 	list_for_each_entry(component, &info->base.adev->children, node) {
@@ -267,6 +269,18 @@ void intel_config_init(struct drm_device *dev)
 		} else if (strcmp(cname, i915_COMPONENT_WORKAROUND) == 0) {
 			if (!alloc_new_node(cl, &info->wa_list))
 				goto bail;
+		} else if (strcmp(cname, i915_COMPONENT_VBIOSTABLE) == 0) {
+			/* Add the main VBT node */
+			if (!alloc_new_node(cl, &info->vbt_list))
+				goto bail;
+
+			/* This adds all the sub device nodes */
+			list_for_each_entry(cl, &component->children, node) {
+				if (!alloc_new_node(cl, &info->vbt_list))
+					goto bail;
+			}
+		} else {
+			DRM_DEBUG_DRIVER("i915/config: Unknown component : %s\n", cname);
 		}
 	}
 
@@ -284,6 +298,8 @@ bail:
 		kfree(new_node);
 	list_for_each_entry_safe(new_node, tmp, &info->wa_list, node)
 		kfree(new_node);
+	list_for_each_entry_safe(new_node, tmp, &info->vbt_list, node)
+		kfree(new_node);
 
 	kfree(info);
 	dev_priv->config_info = NULL;
@@ -318,6 +334,8 @@ void intel_config_shutdown(struct drm_device *dev)
 		kfree(n);
 	list_for_each_entry_safe(n, tmp, &info->wa_list, node)
 		kfree(n);
+	list_for_each_entry_safe(n, tmp, &info->vbt_list, node)
+		kfree(n);
 
 	/* Unload any dynamically loaded ACPI property table */
 	handle = ACPI_HANDLE(dev->dev);
@@ -395,6 +413,8 @@ static struct list_head *cfg_type_to_list(struct intel_config_info *info,
 		return &info->plane_list;
 	case CFG_WORKAROUND:
 		return &info->wa_list;
+	case CFG_VBT:
+		return &info->vbt_list;
 	}
 	return NULL;
 }
@@ -433,6 +453,320 @@ bool intel_config_get_integer(struct drm_i915_private *dev_priv,
 	return false;
 }
 
+static void parse_port_info(struct drm_i915_private *dev_priv,
+			    const union acpi_object *pkg,
+			    int port)
+{
+	u32 supports;
+
+	if (pkg->type != ACPI_TYPE_PACKAGE)
+		return;
+
+	dev_priv->vbt.ddi_port_info[port].hdmi_level_shift =
+		(u32)pkg->package.elements[0].integer.value;
+
+	supports = (u32)pkg->package.elements[1].integer.value;
+	dev_priv->vbt.ddi_port_info[port].supports_dvi  = supports & 0x01;
+	dev_priv->vbt.ddi_port_info[port].supports_hdmi = supports & 0x02;
+	dev_priv->vbt.ddi_port_info[port].supports_dp   = supports & 0x04;
+}
+
+static struct drm_display_mode *parse_mode_info(const union acpi_object *pkg)
+{
+	struct drm_display_mode *mode;
+
+	if (pkg->type != ACPI_TYPE_PACKAGE)
+		return NULL;
+
+	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+	if (!mode || pkg->package.count != 10)
+		return NULL;
+
+	mode->hdisplay = (u32)pkg->package.elements[0].integer.value;
+	mode->hsync_start = (u32)pkg->package.elements[1].integer.value;
+	mode->hsync_end = (u32)pkg->package.elements[3].integer.value;
+	mode->htotal = (u32)pkg->package.elements[3].integer.value;
+	mode->vdisplay = (u32)pkg->package.elements[4].integer.value;
+	mode->vsync_start = (u32)pkg->package.elements[5].integer.value;
+	mode->vsync_end = (u32)pkg->package.elements[6].integer.value;
+	mode->vtotal = (u32)pkg->package.elements[7].integer.value;
+	mode->clock = (u32)pkg->package.elements[8].integer.value;
+	mode->flags = (u32)pkg->package.elements[9].integer.value;
+	mode->type = DRM_MODE_TYPE_PREFERRED;
+
+	return mode;
+}
+
+
+#define PROPERTY_MATCH(prop, name)\
+	(strcasecmp(prop->string.pointer, name) == 0)
+
+/*
+ * Set any general vbt features defined in the ACPI table.
+ */
+static void parse_vbt_general(struct drm_i915_private *dev_priv,
+			      const union acpi_object *properties,
+			      struct acpi_device *adev)
+{
+	const union acpi_object *prop, *name, *value;
+	int i;
+
+	for (i = 0; i < properties->package.count; i++) {
+		prop = &properties->package.elements[i];
+		name = &prop->package.elements[0];
+		value = &prop->package.elements[1];
+
+		if (PROPERTY_MATCH(name, "Internal TV"))
+			dev_priv->vbt.int_tv_support =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "Internal CRT"))
+			dev_priv->vbt.int_crt_support =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "port info A"))
+			parse_port_info(dev_priv, value, PORT_A);
+		else if (PROPERTY_MATCH(name, "port info B"))
+			parse_port_info(dev_priv, value, PORT_B);
+		else if (PROPERTY_MATCH(name, "port info C"))
+			parse_port_info(dev_priv, value, PORT_C);
+		else if (PROPERTY_MATCH(name, "port info D"))
+			parse_port_info(dev_priv, value, PORT_D);
+		else if (PROPERTY_MATCH(name, "port info E"))
+			parse_port_info(dev_priv, value, PORT_E);
+		else if (PROPERTY_MATCH(name, "crt ddc pin"))
+			dev_priv->vbt.crt_ddc_pin = (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "drrs type"))
+			dev_priv->vbt.drrs_type = (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "fdi rx polarity inverted"))
+			dev_priv->vbt.fdi_rx_polarity_inverted =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "display clock mode"))
+			dev_priv->vbt.display_clock_mode =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "mode"))
+			dev_priv->vbt.lfp_lvds_vbt_mode =
+			    parse_mode_info(value);
+	}
+}
+
+static void parse_vbt_lvds(struct drm_i915_private *dev_priv,
+			   const union acpi_object *properties,
+			   struct acpi_device *adev)
+{
+	const union acpi_object *prop, *name, *value;
+	int i;
+
+	for (i = 0; i < properties->package.count; i++) {
+		prop = &properties->package.elements[i];
+		name = &prop->package.elements[0];
+		value = &prop->package.elements[1];
+
+		if (PROPERTY_MATCH(name, "lvds use ssc"))
+			dev_priv->vbt.lvds_use_ssc = (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "LVDS SSC Freq"))
+			dev_priv->vbt.lvds_ssc_freq =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "lvds downclock avail"))
+			dev_priv->lvds_downclock_avail =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "lvds downclock"))
+			dev_priv->lvds_downclock = (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "Pixel Dither"))
+			dev_priv->vbt.lvds_dither = (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "bios lvds val"))
+			dev_priv->vbt.bios_lvds_val =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "lvds vbt"))
+			dev_priv->vbt.lvds_vbt = (u32)value->integer.value;
+	}
+}
+
+static void parse_pwsq(struct drm_i915_private *dev_priv,
+		       const union acpi_object *properties)
+{
+	const union acpi_object *prop, *name, *value;
+	int i;
+
+	for (i = 0; i < properties->package.count; i++) {
+		prop = &properties->package.elements[i];
+		name = &prop->package.elements[0];
+		value = &prop->package.elements[1];
+
+		if (PROPERTY_MATCH(name, "t1/t3"))
+			dev_priv->vbt.edp_pps.t1_t3 =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "t8"))
+			dev_priv->vbt.edp_pps.t8 = (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "t9"))
+			dev_priv->vbt.edp_pps.t9 = (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "t10"))
+			dev_priv->vbt.edp_pps.t10 = (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "t11/t12"))
+			dev_priv->vbt.edp_pps.t11_t12 =
+			    (u32)value->integer.value;
+	}
+}
+
+static void parse_backlight(struct drm_i915_private *dev_priv,
+			    const union acpi_object *properties)
+{
+	const union acpi_object *prop, *name, *value;
+	int i;
+
+	for (i = 0; i < properties->package.count; i++) {
+		prop = &properties->package.elements[i];
+		name = &prop->package.elements[0];
+		value = &prop->package.elements[1];
+
+		if (PROPERTY_MATCH(name, "present"))
+			dev_priv->vbt.backlight.present =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "pwm freq hz"))
+			dev_priv->vbt.backlight.pwm_freq_hz =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "active low pwm"))
+			dev_priv->vbt.backlight.active_low_pwm =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "min brightness"))
+			dev_priv->vbt.backlight.min_brightness =
+			    (u32)value->integer.value;
+	}
+}
+
+static void parse_psr(struct drm_i915_private *dev_priv,
+		      const union acpi_object *properties)
+{
+	const union acpi_object *prop, *name, *value;
+	int i;
+
+	for (i = 0; i < properties->package.count; i++) {
+		prop = &properties->package.elements[i];
+		name = &prop->package.elements[0];
+		value = &prop->package.elements[1];
+
+		if (PROPERTY_MATCH(name, "full link"))
+			dev_priv->vbt.psr.full_link =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "require aux wakeup"))
+			dev_priv->vbt.psr.require_aux_wakeup =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "idle frames"))
+			dev_priv->vbt.psr.idle_frames =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "lines to wait"))
+			dev_priv->vbt.psr.lines_to_wait =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "tp1 wakeup time"))
+			dev_priv->vbt.psr.tp1_wakeup_time =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "tp2 tp3 wakeup time"))
+			dev_priv->vbt.psr.tp2_tp3_wakeup_time =
+			    (u32)value->integer.value;
+	}
+}
+
+static void parse_vbt_edp(struct drm_i915_private *dev_priv,
+			  const union acpi_object *properties,
+			  struct acpi_device *adev)
+{
+	const union acpi_object *prop, *name, *value;
+	int i;
+	struct acpi_device *component;
+
+	/* Child devices for Power sequencing, PSR and Backlight */
+	list_for_each_entry(component, &adev->children, node) {
+		char *sub_section_name;
+		const union acpi_object *properties;
+
+		if (!component)
+			continue;
+
+		sub_section_name = acpi_device_bid(component);
+		properties = component->data.properties;
+
+		if (!properties)
+			continue;
+
+		if (strcmp(sub_section_name, "PWSQ") == 0)
+			parse_pwsq(dev_priv, properties);
+		else if (strcmp(sub_section_name, "BLKT") == 0)
+			parse_backlight(dev_priv, properties);
+		else if (strcmp(sub_section_name, "PSR") == 0)
+			parse_psr(dev_priv, properties);
+	}
+
+	/* Process any EDP port configuration  */
+	for (i = 0; i < properties->package.count; i++) {
+		prop = &properties->package.elements[i];
+		name = &prop->package.elements[0];
+		value = &prop->package.elements[1];
+
+		if (PROPERTY_MATCH(name, "edp bpp"))
+			dev_priv->vbt.edp_bpp = (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "edp pps")) {
+			/*
+			 * The power sequence timing values are stored in
+			 * an array
+			 */
+			dev_priv->vbt.edp_pps.t1_t3 =
+				(u32)value->package.elements[0].integer.value;
+			dev_priv->vbt.edp_pps.t8 =
+				(u32)value->package.elements[1].integer.value;
+			dev_priv->vbt.edp_pps.t9 =
+				(u32)value->package.elements[2].integer.value;
+			dev_priv->vbt.edp_pps.t10 =
+				(u32)value->package.elements[3].integer.value;
+			dev_priv->vbt.edp_pps.t11_t12 =
+				(u32)value->package.elements[4].integer.value;
+		} else if (PROPERTY_MATCH(name, "edp rate"))
+			dev_priv->vbt.edp_rate = (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "edp lanes"))
+			dev_priv->vbt.edp_lanes = (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "edp preemphasis"))
+			dev_priv->vbt.edp_preemphasis =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "edp vswing"))
+			dev_priv->vbt.edp_vswing = (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "edp initialized"))
+			dev_priv->vbt.edp_initialized =
+			    (u32)value->integer.value;
+		else if (PROPERTY_MATCH(name, "edp support"))
+			dev_priv->vbt.edp_support = (u32)value->integer.value;
+	}
+}
+
+/*
+ * Port device configration based on VBT.
+ *
+ * Use the configuration information to overwrite any
+ * corresponding VBT values or provide initial configuration
+ * if VBT doens't exist.
+ */
+void intel_config_vbt(struct drm_i915_private *dev_priv)
+{
+	struct intel_config_info *info = dev_priv->config_info;
+	const union acpi_object *properties;
+	struct list_head *list;
+	struct intel_config_node *n;
+	char *sub_section_name;
+
+	list = cfg_type_to_list(info, CFG_VBT);
+	list_for_each_entry(n, list, node) {
+		sub_section_name = acpi_device_bid(n->adev);
+		properties = n->adev->data.properties;
+		if (!properties)
+			continue;
+
+		/* Call into sub section handlers */
+		if (strcmp(sub_section_name, "VBT") == 0)
+			parse_vbt_general(dev_priv, properties, n->adev);
+		else if (strcmp(sub_section_name, "LVDS") == 0)
+			parse_vbt_lvds(dev_priv, properties, n->adev);
+		else if (strcmp(sub_section_name, "EDP") == 0)
+			parse_vbt_edp(dev_priv, properties, n->adev);
+		else if (strcmp(sub_section_name, "DSI") == 0)
+			DRM_DEBUG_DRIVER("i915/config/vbt: Process Mipi DSI VBT features\n");
+	}
+}
 
 /*
  * Use ACPI methods to enumerate the items in the WA list.
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e2b4e09..cc5da99 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1266,12 +1266,14 @@ enum cfg_type {
 	CFG_CRTC,
 	CFG_CONNECTOR,
 	CFG_PLANE,
-	CFG_WORKAROUND
+	CFG_WORKAROUND,
+	CFG_VBT
 };
 
 void intel_config_init(struct drm_device *dev);
 void intel_config_shutdown(struct drm_device *dev);
 bool intel_config_wa_add(struct drm_i915_private *dev_priv);
+void intel_config_vbt(struct drm_i915_private *dev_priv);
 bool intel_config_get_integer(struct drm_i915_private *dev_priv,
 			  enum cfg_type cfg_type,
 			  const char *name,
-- 
2.1.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [RFC 10/12] drm/i915/config: Introduce a test table and code to make use of it.
  2015-02-12 23:41 [RFC 00/12] i915 init-time configuration Bob Paauwe
                   ` (8 preceding siblings ...)
  2015-02-12 23:41 ` [RFC 09/12] drm/i915/config: Add VBT settings configuration Bob Paauwe
@ 2015-02-12 23:41 ` Bob Paauwe
  2015-02-12 23:41 ` [RFC 11/12] drm/i915/config: Add workaround properties to ACPI table Bob Paauwe
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 32+ messages in thread
From: Bob Paauwe @ 2015-02-12 23:41 UTC (permalink / raw)
  To: intel-gfx

Modify the table loading function to accept an included property table
as a last resort. This can be used to create test cases.  It may
also be used to provide a static, compiled in configuration.

A sample test table (source and compiled HEX version) are included in
this commit.

Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
---
 drivers/gpu/drm/i915/i915-properties.asl | 150 +++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915-properties.hex | 173 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_config.c      |  20 +++-
 3 files changed, 342 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/i915/i915-properties.asl
 create mode 100644 drivers/gpu/drm/i915/i915-properties.hex

diff --git a/drivers/gpu/drm/i915/i915-properties.asl b/drivers/gpu/drm/i915/i915-properties.asl
new file mode 100644
index 0000000..7e9d12b
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915-properties.asl
@@ -0,0 +1,150 @@
+DefinitionBlock ("i915-properties.aml", "SSDT", 5, "", "", 0x00000001)
+{
+	External (DSEN)
+
+	Device (\_SB.PRP) {
+		Device(GFX0) {
+		Name (_ADR, 0x00020000)
+		Name (_HID, "PRP0000")
+
+		Method (_DOS, 1, NotSerialized) {
+			Store (And (Arg0, 0x07), DSEN)
+			If (LEqual (And (Arg0, 0x03), Zero)) {
+			}
+		}
+
+		Name (_DSD, Package() {
+			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+			Package () {
+				Package() {"display_detect", 1},
+				Package() {"fastboot", 1},
+				Package() {"powersave", 0},
+				Package() {"count", 99},
+			}
+		})
+
+		Device (CRTC) {
+			Name (_HID, "PRP0000")
+			Name (_DSD, Package() {
+				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+				Package () {
+					Package() { "enabled", "3" },
+					Package() { "count", 3 }
+				}
+			})
+
+			Device (ID0) {
+				Name (_HID, "PRP0000")
+				Name (_DSD, Package() {
+					ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+					Package () {
+						Package() { "id", 0 },
+						Package() { "canvas_color", Package() { 0, 0, 0 } },
+						Package() { "blend_equ", 0 },
+						Package() { "enabled", 1 }
+					}
+				})
+			}
+
+			Device (ID1) {
+				Name (_HID, "PRP0000")
+				Name (_DSD, Package() {
+					ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+					Package () {
+						Package() { "id", 1 },
+						Package() { "canvas_color", Package() { 0, 0, 0 } },
+						Package() { "blend_equ", 0 },
+						Package() { "enabled", 1 }
+					}
+				})
+			}
+
+			Device (ID2) {
+				Name (_HID, "PRP0000")
+				Name (_DSD, Package() {
+					ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+					Package () {
+						Package() { "id", 2 },
+						Package() { "canvas_color", Package() { 0, 0, 0 } },
+						Package() { "blend_equ", 0 },
+						Package() { "enabled", 1 }
+					}
+				})
+			}
+		}
+
+		Device (PLNS) {
+			Name (_HID, "PRP0000")
+			Name (_DSD, Package() {
+				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+				Package () {
+					Package() { "count", 2 }
+				}
+			})
+
+			Device (PL0) {
+				Name (_HID, "PRP0000")
+				Name (_DSD, Package() {
+					ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+					Package () {
+						Package () { "gamma", 1 },
+						Package () { "color-key", 0xffffffff },
+					}
+				})
+			}
+
+			Device (PL1) {
+				Name (_HID, "PRP0000")
+				Name (_DSD, Package() {
+					ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+					Package () {
+						Package () { "gamma", 0 },
+						Package () { "color-key", 0xffffffff },
+					}
+				})
+			}
+		}
+
+
+		Device (CNCT) {
+			Name (_HID, "PRP0000")
+			Name (_DSD, Package() {
+				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+				Package () {
+					Package() { "count", 2 }
+				}
+			})
+
+			Device(C0) {
+				Name (_HID, "PRP0000")
+				Name (_DSD, Package() {
+					ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+					Package () {
+						Package() { "name", "analog" },
+						Package() { "enabled", 1 },
+						Package() { "bits_per_color", 6 },
+						Package() { "constant_alpha", 255 }
+					}
+				})
+			}
+
+			Device(C1) {
+				Name (_HID, "PRP0000")
+				Name (_DSD, Package() {
+					ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+					Package () {
+						Package() { "name", "displayport_a" },
+						Package() { "enabled", 1 },
+						Package() { "scaling_mode", "Full aspect" },
+						Package() { "audio", "force-dvi" },
+						Package() { "Broadcast_RGB", "Automatic" },
+						Package() { "bits_per_color", 8 },
+						Package() { "constant_alpha", 255 }
+					}
+				})
+			}
+		}
+	}
+	}
+}
+
diff --git a/drivers/gpu/drm/i915/i915-properties.hex b/drivers/gpu/drm/i915/i915-properties.hex
new file mode 100644
index 0000000..0a391eef
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915-properties.hex
@@ -0,0 +1,173 @@
+/*
+ * 
+ * Intel ACPI Component Architecture
+ * ASL Optimizing Compiler version 20131115-64 [Nov 26 2013]
+ * Copyright (c) 2000 - 2013 Intel Corporation
+ * 
+ * Compilation of "i915-properties.asl" - Mon Aug 18 13:16:20 2014
+ * 
+ * C source code output
+ * AML code block contains 0x4EA bytes
+ *
+ */
+unsigned char AmlCode[] =
+{
+    0x53,0x53,0x44,0x54,0xEA,0x04,0x00,0x00,  /* 00000000    "SSDT...." */
+    0x05,0x98,0x00,0x00,0x00,0x00,0x00,0x00,  /* 00000008    "........" */
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  /* 00000010    "........" */
+    0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL" */
+    0x15,0x11,0x13,0x20,0x5B,0x82,0x44,0x4C,  /* 00000020    "... [.DL" */
+    0x5C,0x2E,0x5F,0x53,0x42,0x5F,0x50,0x52,  /* 00000028    "\._SB_PR" */
+    0x50,0x5F,0x5B,0x82,0x46,0x4B,0x47,0x46,  /* 00000030    "P_[.FKGF" */
+    0x58,0x30,0x08,0x5F,0x41,0x44,0x52,0x0C,  /* 00000038    "X0._ADR." */
+    0x00,0x00,0x02,0x00,0x08,0x5F,0x48,0x49,  /* 00000040    "....._HI" */
+    0x44,0x0D,0x50,0x52,0x50,0x30,0x30,0x30,  /* 00000048    "D.PRP000" */
+    0x30,0x00,0x14,0x19,0x5F,0x44,0x4F,0x53,  /* 00000050    "0..._DOS" */
+    0x01,0x70,0x7B,0x68,0x0A,0x07,0x00,0x44,  /* 00000058    ".p{h...D" */
+    0x53,0x45,0x4E,0xA0,0x08,0x93,0x7B,0x68,  /* 00000060    "SEN...{h" */
+    0x0A,0x03,0x00,0x00,0x08,0x5F,0x44,0x53,  /* 00000068    "....._DS" */
+    0x44,0x12,0x47,0x05,0x02,0x11,0x13,0x0A,  /* 00000070    "D.G....." */
+    0x10,0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,  /* 00000078    "......n." */
+    0x4D,0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,  /* 00000080    "M.....J." */
+    0x01,0x12,0x3F,0x04,0x12,0x13,0x02,0x0D,  /* 00000088    "..?....." */
+    0x64,0x69,0x73,0x70,0x6C,0x61,0x79,0x5F,  /* 00000090    "display_" */
+    0x64,0x65,0x74,0x65,0x63,0x74,0x00,0x01,  /* 00000098    "detect.." */
+    0x12,0x0D,0x02,0x0D,0x66,0x61,0x73,0x74,  /* 000000A0    "....fast" */
+    0x62,0x6F,0x6F,0x74,0x00,0x01,0x12,0x0E,  /* 000000A8    "boot...." */
+    0x02,0x0D,0x70,0x6F,0x77,0x65,0x72,0x73,  /* 000000B0    "..powers" */
+    0x61,0x76,0x65,0x00,0x00,0x12,0x0B,0x02,  /* 000000B8    "ave....." */
+    0x0D,0x63,0x6F,0x75,0x6E,0x74,0x00,0x0A,  /* 000000C0    ".count.." */
+    0x63,0x5B,0x82,0x42,0x1A,0x43,0x52,0x54,  /* 000000C8    "c[.B.CRT" */
+    0x43,0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,  /* 000000D0    "C._HID.P" */
+    0x52,0x50,0x30,0x30,0x30,0x30,0x00,0x08,  /* 000000D8    "RP0000.." */
+    0x5F,0x44,0x53,0x44,0x12,0x34,0x02,0x11,  /* 000000E0    "_DSD.4.." */
+    0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,0xBA,  /* 000000E8    "........" */
+    0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,0xBF,  /* 000000F0    "n.M....." */
+    0x4A,0xA3,0x01,0x12,0x1D,0x02,0x12,0x0E,  /* 000000F8    "J......." */
+    0x02,0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,  /* 00000100    "..enable" */
+    0x64,0x00,0x0D,0x33,0x00,0x12,0x0B,0x02,  /* 00000108    "d..3...." */
+    0x0D,0x63,0x6F,0x75,0x6E,0x74,0x00,0x0A,  /* 00000110    ".count.." */
+    0x03,0x5B,0x82,0x4F,0x06,0x49,0x44,0x30,  /* 00000118    ".[.O.ID0" */
+    0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,  /* 00000120    "_._HID.P" */
+    0x52,0x50,0x30,0x30,0x30,0x30,0x00,0x08,  /* 00000128    "RP0000.." */
+    0x5F,0x44,0x53,0x44,0x12,0x45,0x05,0x02,  /* 00000130    "_DSD.E.." */
+    0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,  /* 00000138    "........" */
+    0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,  /* 00000140    ".n.M...." */
+    0xBF,0x4A,0xA3,0x01,0x12,0x3D,0x04,0x12,  /* 00000148    ".J...=.." */
+    0x07,0x02,0x0D,0x69,0x64,0x00,0x00,0x12,  /* 00000150    "...id..." */
+    0x16,0x02,0x0D,0x63,0x61,0x6E,0x76,0x61,  /* 00000158    "...canva" */
+    0x73,0x5F,0x63,0x6F,0x6C,0x6F,0x72,0x00,  /* 00000160    "s_color." */
+    0x12,0x05,0x03,0x00,0x00,0x00,0x12,0x0E,  /* 00000168    "........" */
+    0x02,0x0D,0x62,0x6C,0x65,0x6E,0x64,0x5F,  /* 00000170    "..blend_" */
+    0x65,0x71,0x75,0x00,0x00,0x12,0x0C,0x02,  /* 00000178    "equ....." */
+    0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,0x64,  /* 00000180    ".enabled" */
+    0x00,0x01,0x5B,0x82,0x4F,0x06,0x49,0x44,  /* 00000188    "..[.O.ID" */
+    0x31,0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,  /* 00000190    "1_._HID." */
+    0x50,0x52,0x50,0x30,0x30,0x30,0x30,0x00,  /* 00000198    "PRP0000." */
+    0x08,0x5F,0x44,0x53,0x44,0x12,0x45,0x05,  /* 000001A0    "._DSD.E." */
+    0x02,0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,  /* 000001A8    "........" */
+    0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,  /* 000001B0    "..n.M..." */
+    0x9B,0xBF,0x4A,0xA3,0x01,0x12,0x3D,0x04,  /* 000001B8    "..J...=." */
+    0x12,0x07,0x02,0x0D,0x69,0x64,0x00,0x01,  /* 000001C0    "....id.." */
+    0x12,0x16,0x02,0x0D,0x63,0x61,0x6E,0x76,  /* 000001C8    "....canv" */
+    0x61,0x73,0x5F,0x63,0x6F,0x6C,0x6F,0x72,  /* 000001D0    "as_color" */
+    0x00,0x12,0x05,0x03,0x00,0x00,0x00,0x12,  /* 000001D8    "........" */
+    0x0E,0x02,0x0D,0x62,0x6C,0x65,0x6E,0x64,  /* 000001E0    "...blend" */
+    0x5F,0x65,0x71,0x75,0x00,0x00,0x12,0x0C,  /* 000001E8    "_equ...." */
+    0x02,0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,  /* 000001F0    "..enable" */
+    0x64,0x00,0x01,0x5B,0x82,0x40,0x07,0x49,  /* 000001F8    "d..[.@.I" */
+    0x44,0x32,0x5F,0x08,0x5F,0x48,0x49,0x44,  /* 00000200    "D2_._HID" */
+    0x0D,0x50,0x52,0x50,0x30,0x30,0x30,0x30,  /* 00000208    ".PRP0000" */
+    0x00,0x08,0x5F,0x44,0x53,0x44,0x12,0x46,  /* 00000210    ".._DSD.F" */
+    0x05,0x02,0x11,0x13,0x0A,0x10,0x14,0xD8,  /* 00000218    "........" */
+    0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,0x91,  /* 00000220    "...n.M.." */
+    0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,0x3E,  /* 00000228    "...J...>" */
+    0x04,0x12,0x08,0x02,0x0D,0x69,0x64,0x00,  /* 00000230    ".....id." */
+    0x0A,0x02,0x12,0x16,0x02,0x0D,0x63,0x61,  /* 00000238    "......ca" */
+    0x6E,0x76,0x61,0x73,0x5F,0x63,0x6F,0x6C,  /* 00000240    "nvas_col" */
+    0x6F,0x72,0x00,0x12,0x05,0x03,0x00,0x00,  /* 00000248    "or......" */
+    0x00,0x12,0x0E,0x02,0x0D,0x62,0x6C,0x65,  /* 00000250    ".....ble" */
+    0x6E,0x64,0x5F,0x65,0x71,0x75,0x00,0x00,  /* 00000258    "nd_equ.." */
+    0x12,0x0C,0x02,0x0D,0x65,0x6E,0x61,0x62,  /* 00000260    "....enab" */
+    0x6C,0x65,0x64,0x00,0x01,0x5B,0x82,0x45,  /* 00000268    "led..[.E" */
+    0x0E,0x50,0x4C,0x4E,0x53,0x08,0x5F,0x48,  /* 00000270    ".PLNS._H" */
+    0x49,0x44,0x0D,0x50,0x52,0x50,0x30,0x30,  /* 00000278    "ID.PRP00" */
+    0x30,0x30,0x00,0x08,0x5F,0x44,0x53,0x44,  /* 00000280    "00.._DSD" */
+    0x12,0x25,0x02,0x11,0x13,0x0A,0x10,0x14,  /* 00000288    ".%......" */
+    0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,  /* 00000290    "....n.M." */
+    0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,  /* 00000298    "....J..." */
+    0x0E,0x01,0x12,0x0B,0x02,0x0D,0x63,0x6F,  /* 000002A0    "......co" */
+    0x75,0x6E,0x74,0x00,0x0A,0x02,0x5B,0x82,  /* 000002A8    "unt...[." */
+    0x41,0x05,0x50,0x4C,0x30,0x5F,0x08,0x5F,  /* 000002B0    "A.PL0_._" */
+    0x48,0x49,0x44,0x0D,0x50,0x52,0x50,0x30,  /* 000002B8    "HID.PRP0" */
+    0x30,0x30,0x30,0x00,0x08,0x5F,0x44,0x53,  /* 000002C0    "000.._DS" */
+    0x44,0x12,0x37,0x02,0x11,0x13,0x0A,0x10,  /* 000002C8    "D.7....." */
+    0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,  /* 000002D0    ".....n.M" */
+    0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,  /* 000002D8    ".....J.." */
+    0x12,0x20,0x02,0x12,0x0A,0x02,0x0D,0x67,  /* 000002E0    ". .....g" */
+    0x61,0x6D,0x6D,0x61,0x00,0x01,0x12,0x12,  /* 000002E8    "amma...." */
+    0x02,0x0D,0x63,0x6F,0x6C,0x6F,0x72,0x2D,  /* 000002F0    "..color-" */
+    0x6B,0x65,0x79,0x00,0x0C,0xFF,0xFF,0xFF,  /* 000002F8    "key....." */
+    0xFF,0x5B,0x82,0x41,0x05,0x50,0x4C,0x31,  /* 00000300    ".[.A.PL1" */
+    0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,  /* 00000308    "_._HID.P" */
+    0x52,0x50,0x30,0x30,0x30,0x30,0x00,0x08,  /* 00000310    "RP0000.." */
+    0x5F,0x44,0x53,0x44,0x12,0x37,0x02,0x11,  /* 00000318    "_DSD.7.." */
+    0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,0xBA,  /* 00000320    "........" */
+    0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,0xBF,  /* 00000328    "n.M....." */
+    0x4A,0xA3,0x01,0x12,0x20,0x02,0x12,0x0A,  /* 00000330    "J... ..." */
+    0x02,0x0D,0x67,0x61,0x6D,0x6D,0x61,0x00,  /* 00000338    "..gamma." */
+    0x00,0x12,0x12,0x02,0x0D,0x63,0x6F,0x6C,  /* 00000340    ".....col" */
+    0x6F,0x72,0x2D,0x6B,0x65,0x79,0x00,0x0C,  /* 00000348    "or-key.." */
+    0xFF,0xFF,0xFF,0xFF,0x5B,0x82,0x44,0x19,  /* 00000350    "....[.D." */
+    0x43,0x4E,0x43,0x54,0x08,0x5F,0x48,0x49,  /* 00000358    "CNCT._HI" */
+    0x44,0x0D,0x50,0x52,0x50,0x30,0x30,0x30,  /* 00000360    "D.PRP000" */
+    0x30,0x00,0x08,0x5F,0x44,0x53,0x44,0x12,  /* 00000368    "0.._DSD." */
+    0x25,0x02,0x11,0x13,0x0A,0x10,0x14,0xD8,  /* 00000370    "%......." */
+    0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,0x91,  /* 00000378    "...n.M.." */
+    0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,0x0E,  /* 00000380    "...J...." */
+    0x01,0x12,0x0B,0x02,0x0D,0x63,0x6F,0x75,  /* 00000388    ".....cou" */
+    0x6E,0x74,0x00,0x0A,0x02,0x5B,0x82,0x4D,  /* 00000390    "nt...[.M" */
+    0x07,0x43,0x30,0x5F,0x5F,0x08,0x5F,0x48,  /* 00000398    ".C0__._H" */
+    0x49,0x44,0x0D,0x50,0x52,0x50,0x30,0x30,  /* 000003A0    "ID.PRP00" */
+    0x30,0x30,0x00,0x08,0x5F,0x44,0x53,0x44,  /* 000003A8    "00.._DSD" */
+    0x12,0x43,0x06,0x02,0x11,0x13,0x0A,0x10,  /* 000003B0    ".C......" */
+    0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,  /* 000003B8    ".....n.M" */
+    0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,  /* 000003C0    ".....J.." */
+    0x12,0x4B,0x04,0x04,0x12,0x10,0x02,0x0D,  /* 000003C8    ".K......" */
+    0x6E,0x61,0x6D,0x65,0x00,0x0D,0x61,0x6E,  /* 000003D0    "name..an" */
+    0x61,0x6C,0x6F,0x67,0x00,0x12,0x0C,0x02,  /* 000003D8    "alog...." */
+    0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,0x64,  /* 000003E0    ".enabled" */
+    0x00,0x01,0x12,0x14,0x02,0x0D,0x62,0x69,  /* 000003E8    "......bi" */
+    0x74,0x73,0x5F,0x70,0x65,0x72,0x5F,0x63,  /* 000003F0    "ts_per_c" */
+    0x6F,0x6C,0x6F,0x72,0x00,0x0A,0x06,0x12,  /* 000003F8    "olor...." */
+    0x14,0x02,0x0D,0x63,0x6F,0x6E,0x73,0x74,  /* 00000400    "...const" */
+    0x61,0x6E,0x74,0x5F,0x61,0x6C,0x70,0x68,  /* 00000408    "ant_alph" */
+    0x61,0x00,0x0A,0xFF,0x5B,0x82,0x44,0x0D,  /* 00000410    "a...[.D." */
+    0x43,0x31,0x5F,0x5F,0x08,0x5F,0x48,0x49,  /* 00000418    "C1__._HI" */
+    0x44,0x0D,0x50,0x52,0x50,0x30,0x30,0x30,  /* 00000420    "D.PRP000" */
+    0x30,0x00,0x08,0x5F,0x44,0x53,0x44,0x12,  /* 00000428    "0.._DSD." */
+    0x4A,0x0B,0x02,0x11,0x13,0x0A,0x10,0x14,  /* 00000430    "J......." */
+    0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,  /* 00000438    "....n.M." */
+    0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,  /* 00000440    "....J..." */
+    0x42,0x0A,0x07,0x12,0x17,0x02,0x0D,0x6E,  /* 00000448    "B......n" */
+    0x61,0x6D,0x65,0x00,0x0D,0x64,0x69,0x73,  /* 00000450    "ame..dis" */
+    0x70,0x6C,0x61,0x79,0x70,0x6F,0x72,0x74,  /* 00000458    "playport" */
+    0x5F,0x61,0x00,0x12,0x0C,0x02,0x0D,0x65,  /* 00000460    "_a.....e" */
+    0x6E,0x61,0x62,0x6C,0x65,0x64,0x00,0x01,  /* 00000468    "nabled.." */
+    0x12,0x1D,0x02,0x0D,0x73,0x63,0x61,0x6C,  /* 00000470    "....scal" */
+    0x69,0x6E,0x67,0x5F,0x6D,0x6F,0x64,0x65,  /* 00000478    "ing_mode" */
+    0x00,0x0D,0x46,0x75,0x6C,0x6C,0x20,0x61,  /* 00000480    "..Full a" */
+    0x73,0x70,0x65,0x63,0x74,0x00,0x12,0x14,  /* 00000488    "spect..." */
+    0x02,0x0D,0x61,0x75,0x64,0x69,0x6F,0x00,  /* 00000490    "..audio." */
+    0x0D,0x66,0x6F,0x72,0x63,0x65,0x2D,0x64,  /* 00000498    ".force-d" */
+    0x76,0x69,0x00,0x12,0x1C,0x02,0x0D,0x42,  /* 000004A0    "vi.....B" */
+    0x72,0x6F,0x61,0x64,0x63,0x61,0x73,0x74,  /* 000004A8    "roadcast" */
+    0x5F,0x52,0x47,0x42,0x00,0x0D,0x41,0x75,  /* 000004B0    "_RGB..Au" */
+    0x74,0x6F,0x6D,0x61,0x74,0x69,0x63,0x00,  /* 000004B8    "tomatic." */
+    0x12,0x14,0x02,0x0D,0x62,0x69,0x74,0x73,  /* 000004C0    "....bits" */
+    0x5F,0x70,0x65,0x72,0x5F,0x63,0x6F,0x6C,  /* 000004C8    "_per_col" */
+    0x6F,0x72,0x00,0x0A,0x08,0x12,0x14,0x02,  /* 000004D0    "or......" */
+    0x0D,0x63,0x6F,0x6E,0x73,0x74,0x61,0x6E,  /* 000004D8    ".constan" */
+    0x74,0x5F,0x61,0x6C,0x70,0x68,0x61,0x00,  /* 000004E0    "t_alpha." */
+    0x0A,0xFF                                 /* 000004E8    ".."       */
+};
diff --git a/drivers/gpu/drm/i915/intel_config.c b/drivers/gpu/drm/i915/intel_config.c
index c1b06b7..7db749b 100644
--- a/drivers/gpu/drm/i915/intel_config.c
+++ b/drivers/gpu/drm/i915/intel_config.c
@@ -39,6 +39,17 @@
 #define i915_ACPI_PRP_ROOT "\\_SB.PRP.GFX0"
 
 /*
+ * For testing we insert this fixed table into the ACPI configuration
+ * space. In the real world, this will either be part of the firmware
+ * or inserted into the ACPI configuration space via a well defined
+ * kernel method.
+ *
+ *    iasl -f -tc i915-properties.asl
+ *
+ */
+#include "i915-properties.hex"
+
+/*
  * Load an ACPI property table into the ACPI subsystem.
  *
  * First, verify that a table isn't already loaded.  The table may
@@ -82,7 +93,14 @@ static int intel_acpi_load_table(struct drm_device *dev, char *firmware)
 			DRM_ERROR("Failed to find ACPI table %s: %d\n",
 				  firmware, ret);
 			fw = NULL;
-			goto bad_table;
+
+			/*
+			 * A static ACPI table can be linked into the code.
+			 * This is used primarily for testing out the code
+			 * but can also be used with a driver compiled
+			 * into the kernel for an embedded type configuration.
+			 */
+			table = (struct acpi_table_header *)AmlCode;
 		} else {
 			table = (struct acpi_table_header *)fw->data;
 		}
-- 
2.1.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [RFC 11/12] drm/i915/config: Add workaround properties to ACPI table.
  2015-02-12 23:41 [RFC 00/12] i915 init-time configuration Bob Paauwe
                   ` (9 preceding siblings ...)
  2015-02-12 23:41 ` [RFC 10/12] drm/i915/config: Introduce a test table and code to make use of it Bob Paauwe
@ 2015-02-12 23:41 ` Bob Paauwe
  2015-02-12 23:41 ` [RFC 12/12] drm/i915/config: Add ACPI device examples for VBT configuration Bob Paauwe
  2015-02-13  8:08 ` [RFC 00/12] i915 init-time configuration Jani Nikula
  12 siblings, 0 replies; 32+ messages in thread
From: Bob Paauwe @ 2015-02-12 23:41 UTC (permalink / raw)
  To: intel-gfx

Add the various workarounds as properties in the ACPI table. How these
get processed and used is still TBD.
Added broadwell and cherrytrail workarounds as examples.

Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
---
 drivers/gpu/drm/i915/i915-properties.asl |  50 +++++
 drivers/gpu/drm/i915/i915-properties.hex | 352 +++++++++++++++++++------------
 2 files changed, 262 insertions(+), 140 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915-properties.asl b/drivers/gpu/drm/i915/i915-properties.asl
index 7e9d12b..cdd4438 100644
--- a/drivers/gpu/drm/i915/i915-properties.asl
+++ b/drivers/gpu/drm/i915/i915-properties.asl
@@ -23,6 +23,56 @@ DefinitionBlock ("i915-properties.aml", "SSDT", 5, "", "", 0x00000001)
 			}
 		})
 
+		Device (WRKS) {
+			Name (_HID, "PRP0000")
+			Name (_DSD, Package() {
+				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+				Package () {
+					// Should there be some way to identify the hardware
+					// and use that to control if these are applied or
+					// not?
+
+					// Workaround "name", addr, value, mask, flags
+
+					// CherryView workarounds
+					Package () { "WaDisablePartialInstShootdown",
+							package() { 0xe4f0, 0x100, 0x100, 0x1 }},
+
+					Package () { "WaDisableThreadStallDopClockGating",
+							package() { 0xe4f0, 0x20, 0x20, 0x1 }},
+
+					Package () { "WaDisableDopClockGating",
+							package() { 0xe4f4, 0x1, 0x1, 0x1 }},
+
+					Package () { "WaDisableSamplerPowerBypass",
+							package() { 0xe184, 0x2, 0x2, 0x1 }},
+
+					// Broadwell workarounds
+					Package () { "WaDisablePartialInstShootdown",
+							package() { 0xe4f0, 0x100, 0x100, 0x1 }},
+
+					Package () { "WaDisableThreadStallDopClockGating",
+							package() { 0xe4f0, 0x20, 0x20, 0x1 }},
+
+					Package () { "WaDisableDopClockGating",
+							package() { 0xe4f4, 0x1, 0x1, 0x1 }},
+					Package () { "WaDisableDopClockGating",
+							package() { 0xe184, 0x2, 0x2, 0x1 }},
+
+					Package () { "WaDisableFenceDestinationToSLM",
+							package() { 0x7300, 0x10, 0x10, 0x1 }},
+					Package () { "WaDisableFenceDestinationToSLM GT3",
+							package() { 0x7300, 0x4000, 0x4000, 0x1 }},
+
+					Package () { "Wa4x4STCOptimizationDisable",
+							package() { 0x7004, 0x40, 0x40, 0x1 }},
+
+					Package () { "Wa16x4hashing",
+							package() { 0x7008, 0x200, 0x280, 0x1 }},
+				}
+			})
+		}
+
 		Device (CRTC) {
 			Name (_HID, "PRP0000")
 			Name (_DSD, Package() {
diff --git a/drivers/gpu/drm/i915/i915-properties.hex b/drivers/gpu/drm/i915/i915-properties.hex
index 0a391eef..c42c749 100644
--- a/drivers/gpu/drm/i915/i915-properties.hex
+++ b/drivers/gpu/drm/i915/i915-properties.hex
@@ -1,24 +1,24 @@
 /*
  * 
  * Intel ACPI Component Architecture
- * ASL Optimizing Compiler version 20131115-64 [Nov 26 2013]
- * Copyright (c) 2000 - 2013 Intel Corporation
+ * ASL+ Optimizing Compiler version 20141107-64 [Dec  2 2014]
+ * Copyright (c) 2000 - 2014 Intel Corporation
  * 
- * Compilation of "i915-properties.asl" - Mon Aug 18 13:16:20 2014
+ * Compilation of "i915-properties.asl" - Fri Feb  6 14:29:03 2015
  * 
  * C source code output
- * AML code block contains 0x4EA bytes
+ * AML code block contains 0x72B bytes
  *
  */
 unsigned char AmlCode[] =
 {
-    0x53,0x53,0x44,0x54,0xEA,0x04,0x00,0x00,  /* 00000000    "SSDT...." */
-    0x05,0x98,0x00,0x00,0x00,0x00,0x00,0x00,  /* 00000008    "........" */
+    0x53,0x53,0x44,0x54,0x2B,0x07,0x00,0x00,  /* 00000000    "SSDT+..." */
+    0x05,0x39,0x00,0x00,0x00,0x00,0x00,0x00,  /* 00000008    ".9......" */
     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  /* 00000010    "........" */
     0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL" */
-    0x15,0x11,0x13,0x20,0x5B,0x82,0x44,0x4C,  /* 00000020    "... [.DL" */
+    0x07,0x11,0x14,0x20,0x5B,0x82,0x45,0x70,  /* 00000020    "... [.Ep" */
     0x5C,0x2E,0x5F,0x53,0x42,0x5F,0x50,0x52,  /* 00000028    "\._SB_PR" */
-    0x50,0x5F,0x5B,0x82,0x46,0x4B,0x47,0x46,  /* 00000030    "P_[.FKGF" */
+    0x50,0x5F,0x5B,0x82,0x47,0x6F,0x47,0x46,  /* 00000030    "P_[.GoGF" */
     0x58,0x30,0x08,0x5F,0x41,0x44,0x52,0x0C,  /* 00000038    "X0._ADR." */
     0x00,0x00,0x02,0x00,0x08,0x5F,0x48,0x49,  /* 00000040    "....._HI" */
     0x44,0x0D,0x50,0x52,0x50,0x30,0x30,0x30,  /* 00000048    "D.PRP000" */
@@ -37,137 +37,209 @@ unsigned char AmlCode[] =
     0x02,0x0D,0x70,0x6F,0x77,0x65,0x72,0x73,  /* 000000B0    "..powers" */
     0x61,0x76,0x65,0x00,0x00,0x12,0x0B,0x02,  /* 000000B8    "ave....." */
     0x0D,0x63,0x6F,0x75,0x6E,0x74,0x00,0x0A,  /* 000000C0    ".count.." */
-    0x63,0x5B,0x82,0x42,0x1A,0x43,0x52,0x54,  /* 000000C8    "c[.B.CRT" */
-    0x43,0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,  /* 000000D0    "C._HID.P" */
+    0x63,0x5B,0x82,0x4F,0x23,0x57,0x52,0x4B,  /* 000000C8    "c[.O#WRK" */
+    0x53,0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,  /* 000000D0    "S._HID.P" */
     0x52,0x50,0x30,0x30,0x30,0x30,0x00,0x08,  /* 000000D8    "RP0000.." */
-    0x5F,0x44,0x53,0x44,0x12,0x34,0x02,0x11,  /* 000000E0    "_DSD.4.." */
-    0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,0xBA,  /* 000000E8    "........" */
-    0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,0xBF,  /* 000000F0    "n.M....." */
-    0x4A,0xA3,0x01,0x12,0x1D,0x02,0x12,0x0E,  /* 000000F8    "J......." */
-    0x02,0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,  /* 00000100    "..enable" */
-    0x64,0x00,0x0D,0x33,0x00,0x12,0x0B,0x02,  /* 00000108    "d..3...." */
-    0x0D,0x63,0x6F,0x75,0x6E,0x74,0x00,0x0A,  /* 00000110    ".count.." */
-    0x03,0x5B,0x82,0x4F,0x06,0x49,0x44,0x30,  /* 00000118    ".[.O.ID0" */
-    0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,  /* 00000120    "_._HID.P" */
-    0x52,0x50,0x30,0x30,0x30,0x30,0x00,0x08,  /* 00000128    "RP0000.." */
-    0x5F,0x44,0x53,0x44,0x12,0x45,0x05,0x02,  /* 00000130    "_DSD.E.." */
-    0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,  /* 00000138    "........" */
-    0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,  /* 00000140    ".n.M...." */
-    0xBF,0x4A,0xA3,0x01,0x12,0x3D,0x04,0x12,  /* 00000148    ".J...=.." */
-    0x07,0x02,0x0D,0x69,0x64,0x00,0x00,0x12,  /* 00000150    "...id..." */
-    0x16,0x02,0x0D,0x63,0x61,0x6E,0x76,0x61,  /* 00000158    "...canva" */
-    0x73,0x5F,0x63,0x6F,0x6C,0x6F,0x72,0x00,  /* 00000160    "s_color." */
-    0x12,0x05,0x03,0x00,0x00,0x00,0x12,0x0E,  /* 00000168    "........" */
-    0x02,0x0D,0x62,0x6C,0x65,0x6E,0x64,0x5F,  /* 00000170    "..blend_" */
-    0x65,0x71,0x75,0x00,0x00,0x12,0x0C,0x02,  /* 00000178    "equ....." */
-    0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,0x64,  /* 00000180    ".enabled" */
-    0x00,0x01,0x5B,0x82,0x4F,0x06,0x49,0x44,  /* 00000188    "..[.O.ID" */
-    0x31,0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,  /* 00000190    "1_._HID." */
-    0x50,0x52,0x50,0x30,0x30,0x30,0x30,0x00,  /* 00000198    "PRP0000." */
-    0x08,0x5F,0x44,0x53,0x44,0x12,0x45,0x05,  /* 000001A0    "._DSD.E." */
-    0x02,0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,  /* 000001A8    "........" */
-    0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,  /* 000001B0    "..n.M..." */
-    0x9B,0xBF,0x4A,0xA3,0x01,0x12,0x3D,0x04,  /* 000001B8    "..J...=." */
-    0x12,0x07,0x02,0x0D,0x69,0x64,0x00,0x01,  /* 000001C0    "....id.." */
-    0x12,0x16,0x02,0x0D,0x63,0x61,0x6E,0x76,  /* 000001C8    "....canv" */
-    0x61,0x73,0x5F,0x63,0x6F,0x6C,0x6F,0x72,  /* 000001D0    "as_color" */
-    0x00,0x12,0x05,0x03,0x00,0x00,0x00,0x12,  /* 000001D8    "........" */
-    0x0E,0x02,0x0D,0x62,0x6C,0x65,0x6E,0x64,  /* 000001E0    "...blend" */
-    0x5F,0x65,0x71,0x75,0x00,0x00,0x12,0x0C,  /* 000001E8    "_equ...." */
-    0x02,0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,  /* 000001F0    "..enable" */
-    0x64,0x00,0x01,0x5B,0x82,0x40,0x07,0x49,  /* 000001F8    "d..[.@.I" */
-    0x44,0x32,0x5F,0x08,0x5F,0x48,0x49,0x44,  /* 00000200    "D2_._HID" */
-    0x0D,0x50,0x52,0x50,0x30,0x30,0x30,0x30,  /* 00000208    ".PRP0000" */
-    0x00,0x08,0x5F,0x44,0x53,0x44,0x12,0x46,  /* 00000210    ".._DSD.F" */
-    0x05,0x02,0x11,0x13,0x0A,0x10,0x14,0xD8,  /* 00000218    "........" */
-    0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,0x91,  /* 00000220    "...n.M.." */
-    0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,0x3E,  /* 00000228    "...J...>" */
-    0x04,0x12,0x08,0x02,0x0D,0x69,0x64,0x00,  /* 00000230    ".....id." */
-    0x0A,0x02,0x12,0x16,0x02,0x0D,0x63,0x61,  /* 00000238    "......ca" */
-    0x6E,0x76,0x61,0x73,0x5F,0x63,0x6F,0x6C,  /* 00000240    "nvas_col" */
-    0x6F,0x72,0x00,0x12,0x05,0x03,0x00,0x00,  /* 00000248    "or......" */
-    0x00,0x12,0x0E,0x02,0x0D,0x62,0x6C,0x65,  /* 00000250    ".....ble" */
-    0x6E,0x64,0x5F,0x65,0x71,0x75,0x00,0x00,  /* 00000258    "nd_equ.." */
-    0x12,0x0C,0x02,0x0D,0x65,0x6E,0x61,0x62,  /* 00000260    "....enab" */
-    0x6C,0x65,0x64,0x00,0x01,0x5B,0x82,0x45,  /* 00000268    "led..[.E" */
-    0x0E,0x50,0x4C,0x4E,0x53,0x08,0x5F,0x48,  /* 00000270    ".PLNS._H" */
-    0x49,0x44,0x0D,0x50,0x52,0x50,0x30,0x30,  /* 00000278    "ID.PRP00" */
-    0x30,0x30,0x00,0x08,0x5F,0x44,0x53,0x44,  /* 00000280    "00.._DSD" */
-    0x12,0x25,0x02,0x11,0x13,0x0A,0x10,0x14,  /* 00000288    ".%......" */
-    0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,  /* 00000290    "....n.M." */
-    0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,  /* 00000298    "....J..." */
-    0x0E,0x01,0x12,0x0B,0x02,0x0D,0x63,0x6F,  /* 000002A0    "......co" */
-    0x75,0x6E,0x74,0x00,0x0A,0x02,0x5B,0x82,  /* 000002A8    "unt...[." */
-    0x41,0x05,0x50,0x4C,0x30,0x5F,0x08,0x5F,  /* 000002B0    "A.PL0_._" */
-    0x48,0x49,0x44,0x0D,0x50,0x52,0x50,0x30,  /* 000002B8    "HID.PRP0" */
-    0x30,0x30,0x30,0x00,0x08,0x5F,0x44,0x53,  /* 000002C0    "000.._DS" */
-    0x44,0x12,0x37,0x02,0x11,0x13,0x0A,0x10,  /* 000002C8    "D.7....." */
-    0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,  /* 000002D0    ".....n.M" */
-    0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,  /* 000002D8    ".....J.." */
-    0x12,0x20,0x02,0x12,0x0A,0x02,0x0D,0x67,  /* 000002E0    ". .....g" */
-    0x61,0x6D,0x6D,0x61,0x00,0x01,0x12,0x12,  /* 000002E8    "amma...." */
-    0x02,0x0D,0x63,0x6F,0x6C,0x6F,0x72,0x2D,  /* 000002F0    "..color-" */
-    0x6B,0x65,0x79,0x00,0x0C,0xFF,0xFF,0xFF,  /* 000002F8    "key....." */
-    0xFF,0x5B,0x82,0x41,0x05,0x50,0x4C,0x31,  /* 00000300    ".[.A.PL1" */
-    0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,  /* 00000308    "_._HID.P" */
-    0x52,0x50,0x30,0x30,0x30,0x30,0x00,0x08,  /* 00000310    "RP0000.." */
-    0x5F,0x44,0x53,0x44,0x12,0x37,0x02,0x11,  /* 00000318    "_DSD.7.." */
-    0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,0xBA,  /* 00000320    "........" */
-    0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,0xBF,  /* 00000328    "n.M....." */
-    0x4A,0xA3,0x01,0x12,0x20,0x02,0x12,0x0A,  /* 00000330    "J... ..." */
-    0x02,0x0D,0x67,0x61,0x6D,0x6D,0x61,0x00,  /* 00000338    "..gamma." */
-    0x00,0x12,0x12,0x02,0x0D,0x63,0x6F,0x6C,  /* 00000340    ".....col" */
-    0x6F,0x72,0x2D,0x6B,0x65,0x79,0x00,0x0C,  /* 00000348    "or-key.." */
-    0xFF,0xFF,0xFF,0xFF,0x5B,0x82,0x44,0x19,  /* 00000350    "....[.D." */
-    0x43,0x4E,0x43,0x54,0x08,0x5F,0x48,0x49,  /* 00000358    "CNCT._HI" */
-    0x44,0x0D,0x50,0x52,0x50,0x30,0x30,0x30,  /* 00000360    "D.PRP000" */
-    0x30,0x00,0x08,0x5F,0x44,0x53,0x44,0x12,  /* 00000368    "0.._DSD." */
-    0x25,0x02,0x11,0x13,0x0A,0x10,0x14,0xD8,  /* 00000370    "%......." */
-    0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,0x91,  /* 00000378    "...n.M.." */
-    0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,0x0E,  /* 00000380    "...J...." */
-    0x01,0x12,0x0B,0x02,0x0D,0x63,0x6F,0x75,  /* 00000388    ".....cou" */
-    0x6E,0x74,0x00,0x0A,0x02,0x5B,0x82,0x4D,  /* 00000390    "nt...[.M" */
-    0x07,0x43,0x30,0x5F,0x5F,0x08,0x5F,0x48,  /* 00000398    ".C0__._H" */
-    0x49,0x44,0x0D,0x50,0x52,0x50,0x30,0x30,  /* 000003A0    "ID.PRP00" */
-    0x30,0x30,0x00,0x08,0x5F,0x44,0x53,0x44,  /* 000003A8    "00.._DSD" */
-    0x12,0x43,0x06,0x02,0x11,0x13,0x0A,0x10,  /* 000003B0    ".C......" */
-    0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,  /* 000003B8    ".....n.M" */
-    0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,  /* 000003C0    ".....J.." */
-    0x12,0x4B,0x04,0x04,0x12,0x10,0x02,0x0D,  /* 000003C8    ".K......" */
-    0x6E,0x61,0x6D,0x65,0x00,0x0D,0x61,0x6E,  /* 000003D0    "name..an" */
-    0x61,0x6C,0x6F,0x67,0x00,0x12,0x0C,0x02,  /* 000003D8    "alog...." */
-    0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,0x64,  /* 000003E0    ".enabled" */
-    0x00,0x01,0x12,0x14,0x02,0x0D,0x62,0x69,  /* 000003E8    "......bi" */
-    0x74,0x73,0x5F,0x70,0x65,0x72,0x5F,0x63,  /* 000003F0    "ts_per_c" */
-    0x6F,0x6C,0x6F,0x72,0x00,0x0A,0x06,0x12,  /* 000003F8    "olor...." */
-    0x14,0x02,0x0D,0x63,0x6F,0x6E,0x73,0x74,  /* 00000400    "...const" */
-    0x61,0x6E,0x74,0x5F,0x61,0x6C,0x70,0x68,  /* 00000408    "ant_alph" */
-    0x61,0x00,0x0A,0xFF,0x5B,0x82,0x44,0x0D,  /* 00000410    "a...[.D." */
-    0x43,0x31,0x5F,0x5F,0x08,0x5F,0x48,0x49,  /* 00000418    "C1__._HI" */
-    0x44,0x0D,0x50,0x52,0x50,0x30,0x30,0x30,  /* 00000420    "D.PRP000" */
-    0x30,0x00,0x08,0x5F,0x44,0x53,0x44,0x12,  /* 00000428    "0.._DSD." */
-    0x4A,0x0B,0x02,0x11,0x13,0x0A,0x10,0x14,  /* 00000430    "J......." */
-    0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,  /* 00000438    "....n.M." */
-    0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,  /* 00000440    "....J..." */
-    0x42,0x0A,0x07,0x12,0x17,0x02,0x0D,0x6E,  /* 00000448    "B......n" */
-    0x61,0x6D,0x65,0x00,0x0D,0x64,0x69,0x73,  /* 00000450    "ame..dis" */
-    0x70,0x6C,0x61,0x79,0x70,0x6F,0x72,0x74,  /* 00000458    "playport" */
-    0x5F,0x61,0x00,0x12,0x0C,0x02,0x0D,0x65,  /* 00000460    "_a.....e" */
-    0x6E,0x61,0x62,0x6C,0x65,0x64,0x00,0x01,  /* 00000468    "nabled.." */
-    0x12,0x1D,0x02,0x0D,0x73,0x63,0x61,0x6C,  /* 00000470    "....scal" */
-    0x69,0x6E,0x67,0x5F,0x6D,0x6F,0x64,0x65,  /* 00000478    "ing_mode" */
-    0x00,0x0D,0x46,0x75,0x6C,0x6C,0x20,0x61,  /* 00000480    "..Full a" */
-    0x73,0x70,0x65,0x63,0x74,0x00,0x12,0x14,  /* 00000488    "spect..." */
-    0x02,0x0D,0x61,0x75,0x64,0x69,0x6F,0x00,  /* 00000490    "..audio." */
-    0x0D,0x66,0x6F,0x72,0x63,0x65,0x2D,0x64,  /* 00000498    ".force-d" */
-    0x76,0x69,0x00,0x12,0x1C,0x02,0x0D,0x42,  /* 000004A0    "vi.....B" */
-    0x72,0x6F,0x61,0x64,0x63,0x61,0x73,0x74,  /* 000004A8    "roadcast" */
-    0x5F,0x52,0x47,0x42,0x00,0x0D,0x41,0x75,  /* 000004B0    "_RGB..Au" */
-    0x74,0x6F,0x6D,0x61,0x74,0x69,0x63,0x00,  /* 000004B8    "tomatic." */
-    0x12,0x14,0x02,0x0D,0x62,0x69,0x74,0x73,  /* 000004C0    "....bits" */
-    0x5F,0x70,0x65,0x72,0x5F,0x63,0x6F,0x6C,  /* 000004C8    "_per_col" */
-    0x6F,0x72,0x00,0x0A,0x08,0x12,0x14,0x02,  /* 000004D0    "or......" */
-    0x0D,0x63,0x6F,0x6E,0x73,0x74,0x61,0x6E,  /* 000004D8    ".constan" */
-    0x74,0x5F,0x61,0x6C,0x70,0x68,0x61,0x00,  /* 000004E0    "t_alpha." */
-    0x0A,0xFF                                 /* 000004E8    ".."       */
+    0x5F,0x44,0x53,0x44,0x12,0x45,0x22,0x02,  /* 000000E0    "_DSD.E"." */
+    0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,  /* 000000E8    "........" */
+    0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,  /* 000000F0    ".n.M...." */
+    0xBF,0x4A,0xA3,0x01,0x12,0x4D,0x20,0x0C,  /* 000000F8    ".J...M ." */
+    0x12,0x2E,0x02,0x0D,0x57,0x61,0x44,0x69,  /* 00000100    "....WaDi" */
+    0x73,0x61,0x62,0x6C,0x65,0x50,0x61,0x72,  /* 00000108    "sablePar" */
+    0x74,0x69,0x61,0x6C,0x49,0x6E,0x73,0x74,  /* 00000110    "tialInst" */
+    0x53,0x68,0x6F,0x6F,0x74,0x64,0x6F,0x77,  /* 00000118    "Shootdow" */
+    0x6E,0x00,0x12,0x0C,0x04,0x0B,0xF0,0xE4,  /* 00000120    "n......." */
+    0x0B,0x00,0x01,0x0B,0x00,0x01,0x01,0x12,  /* 00000128    "........" */
+    0x31,0x02,0x0D,0x57,0x61,0x44,0x69,0x73,  /* 00000130    "1..WaDis" */
+    0x61,0x62,0x6C,0x65,0x54,0x68,0x72,0x65,  /* 00000138    "ableThre" */
+    0x61,0x64,0x53,0x74,0x61,0x6C,0x6C,0x44,  /* 00000140    "adStallD" */
+    0x6F,0x70,0x43,0x6C,0x6F,0x63,0x6B,0x47,  /* 00000148    "opClockG" */
+    0x61,0x74,0x69,0x6E,0x67,0x00,0x12,0x0A,  /* 00000150    "ating..." */
+    0x04,0x0B,0xF0,0xE4,0x0A,0x20,0x0A,0x20,  /* 00000158    "..... . " */
+    0x01,0x12,0x24,0x02,0x0D,0x57,0x61,0x44,  /* 00000160    "..$..WaD" */
+    0x69,0x73,0x61,0x62,0x6C,0x65,0x44,0x6F,  /* 00000168    "isableDo" */
+    0x70,0x43,0x6C,0x6F,0x63,0x6B,0x47,0x61,  /* 00000170    "pClockGa" */
+    0x74,0x69,0x6E,0x67,0x00,0x12,0x08,0x04,  /* 00000178    "ting...." */
+    0x0B,0xF4,0xE4,0x01,0x01,0x01,0x12,0x2A,  /* 00000180    ".......*" */
+    0x02,0x0D,0x57,0x61,0x44,0x69,0x73,0x61,  /* 00000188    "..WaDisa" */
+    0x62,0x6C,0x65,0x53,0x61,0x6D,0x70,0x6C,  /* 00000190    "bleSampl" */
+    0x65,0x72,0x50,0x6F,0x77,0x65,0x72,0x42,  /* 00000198    "erPowerB" */
+    0x79,0x70,0x61,0x73,0x73,0x00,0x12,0x0A,  /* 000001A0    "ypass..." */
+    0x04,0x0B,0x84,0xE1,0x0A,0x02,0x0A,0x02,  /* 000001A8    "........" */
+    0x01,0x12,0x2E,0x02,0x0D,0x57,0x61,0x44,  /* 000001B0    ".....WaD" */
+    0x69,0x73,0x61,0x62,0x6C,0x65,0x50,0x61,  /* 000001B8    "isablePa" */
+    0x72,0x74,0x69,0x61,0x6C,0x49,0x6E,0x73,  /* 000001C0    "rtialIns" */
+    0x74,0x53,0x68,0x6F,0x6F,0x74,0x64,0x6F,  /* 000001C8    "tShootdo" */
+    0x77,0x6E,0x00,0x12,0x0C,0x04,0x0B,0xF0,  /* 000001D0    "wn......" */
+    0xE4,0x0B,0x00,0x01,0x0B,0x00,0x01,0x01,  /* 000001D8    "........" */
+    0x12,0x31,0x02,0x0D,0x57,0x61,0x44,0x69,  /* 000001E0    ".1..WaDi" */
+    0x73,0x61,0x62,0x6C,0x65,0x54,0x68,0x72,  /* 000001E8    "sableThr" */
+    0x65,0x61,0x64,0x53,0x74,0x61,0x6C,0x6C,  /* 000001F0    "eadStall" */
+    0x44,0x6F,0x70,0x43,0x6C,0x6F,0x63,0x6B,  /* 000001F8    "DopClock" */
+    0x47,0x61,0x74,0x69,0x6E,0x67,0x00,0x12,  /* 00000200    "Gating.." */
+    0x0A,0x04,0x0B,0xF0,0xE4,0x0A,0x20,0x0A,  /* 00000208    "...... ." */
+    0x20,0x01,0x12,0x24,0x02,0x0D,0x57,0x61,  /* 00000210    " ..$..Wa" */
+    0x44,0x69,0x73,0x61,0x62,0x6C,0x65,0x44,  /* 00000218    "DisableD" */
+    0x6F,0x70,0x43,0x6C,0x6F,0x63,0x6B,0x47,  /* 00000220    "opClockG" */
+    0x61,0x74,0x69,0x6E,0x67,0x00,0x12,0x08,  /* 00000228    "ating..." */
+    0x04,0x0B,0xF4,0xE4,0x01,0x01,0x01,0x12,  /* 00000230    "........" */
+    0x26,0x02,0x0D,0x57,0x61,0x44,0x69,0x73,  /* 00000238    "&..WaDis" */
+    0x61,0x62,0x6C,0x65,0x44,0x6F,0x70,0x43,  /* 00000240    "ableDopC" */
+    0x6C,0x6F,0x63,0x6B,0x47,0x61,0x74,0x69,  /* 00000248    "lockGati" */
+    0x6E,0x67,0x00,0x12,0x0A,0x04,0x0B,0x84,  /* 00000250    "ng......" */
+    0xE1,0x0A,0x02,0x0A,0x02,0x01,0x12,0x2D,  /* 00000258    ".......-" */
+    0x02,0x0D,0x57,0x61,0x44,0x69,0x73,0x61,  /* 00000260    "..WaDisa" */
+    0x62,0x6C,0x65,0x46,0x65,0x6E,0x63,0x65,  /* 00000268    "bleFence" */
+    0x44,0x65,0x73,0x74,0x69,0x6E,0x61,0x74,  /* 00000270    "Destinat" */
+    0x69,0x6F,0x6E,0x54,0x6F,0x53,0x4C,0x4D,  /* 00000278    "ionToSLM" */
+    0x00,0x12,0x0A,0x04,0x0B,0x00,0x73,0x0A,  /* 00000280    "......s." */
+    0x10,0x0A,0x10,0x01,0x12,0x33,0x02,0x0D,  /* 00000288    ".....3.." */
+    0x57,0x61,0x44,0x69,0x73,0x61,0x62,0x6C,  /* 00000290    "WaDisabl" */
+    0x65,0x46,0x65,0x6E,0x63,0x65,0x44,0x65,  /* 00000298    "eFenceDe" */
+    0x73,0x74,0x69,0x6E,0x61,0x74,0x69,0x6F,  /* 000002A0    "stinatio" */
+    0x6E,0x54,0x6F,0x53,0x4C,0x4D,0x20,0x47,  /* 000002A8    "nToSLM G" */
+    0x54,0x33,0x00,0x12,0x0C,0x04,0x0B,0x00,  /* 000002B0    "T3......" */
+    0x73,0x0B,0x00,0x40,0x0B,0x00,0x40,0x01,  /* 000002B8    "s..@..@." */
+    0x12,0x2A,0x02,0x0D,0x57,0x61,0x34,0x78,  /* 000002C0    ".*..Wa4x" */
+    0x34,0x53,0x54,0x43,0x4F,0x70,0x74,0x69,  /* 000002C8    "4STCOpti" */
+    0x6D,0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,  /* 000002D0    "mization" */
+    0x44,0x69,0x73,0x61,0x62,0x6C,0x65,0x00,  /* 000002D8    "Disable." */
+    0x12,0x0A,0x04,0x0B,0x04,0x70,0x0A,0x40,  /* 000002E0    ".....p.@" */
+    0x0A,0x40,0x01,0x12,0x1E,0x02,0x0D,0x57,  /* 000002E8    ".@.....W" */
+    0x61,0x31,0x36,0x78,0x34,0x68,0x61,0x73,  /* 000002F0    "a16x4has" */
+    0x68,0x69,0x6E,0x67,0x00,0x12,0x0C,0x04,  /* 000002F8    "hing...." */
+    0x0B,0x08,0x70,0x0B,0x00,0x02,0x0B,0x80,  /* 00000300    "..p....." */
+    0x02,0x01,0x5B,0x82,0x42,0x1A,0x43,0x52,  /* 00000308    "..[.B.CR" */
+    0x54,0x43,0x08,0x5F,0x48,0x49,0x44,0x0D,  /* 00000310    "TC._HID." */
+    0x50,0x52,0x50,0x30,0x30,0x30,0x30,0x00,  /* 00000318    "PRP0000." */
+    0x08,0x5F,0x44,0x53,0x44,0x12,0x34,0x02,  /* 00000320    "._DSD.4." */
+    0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,  /* 00000328    "........" */
+    0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,  /* 00000330    ".n.M...." */
+    0xBF,0x4A,0xA3,0x01,0x12,0x1D,0x02,0x12,  /* 00000338    ".J......" */
+    0x0E,0x02,0x0D,0x65,0x6E,0x61,0x62,0x6C,  /* 00000340    "...enabl" */
+    0x65,0x64,0x00,0x0D,0x33,0x00,0x12,0x0B,  /* 00000348    "ed..3..." */
+    0x02,0x0D,0x63,0x6F,0x75,0x6E,0x74,0x00,  /* 00000350    "..count." */
+    0x0A,0x03,0x5B,0x82,0x4F,0x06,0x49,0x44,  /* 00000358    "..[.O.ID" */
+    0x30,0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,  /* 00000360    "0_._HID." */
+    0x50,0x52,0x50,0x30,0x30,0x30,0x30,0x00,  /* 00000368    "PRP0000." */
+    0x08,0x5F,0x44,0x53,0x44,0x12,0x45,0x05,  /* 00000370    "._DSD.E." */
+    0x02,0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,  /* 00000378    "........" */
+    0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,  /* 00000380    "..n.M..." */
+    0x9B,0xBF,0x4A,0xA3,0x01,0x12,0x3D,0x04,  /* 00000388    "..J...=." */
+    0x12,0x07,0x02,0x0D,0x69,0x64,0x00,0x00,  /* 00000390    "....id.." */
+    0x12,0x16,0x02,0x0D,0x63,0x61,0x6E,0x76,  /* 00000398    "....canv" */
+    0x61,0x73,0x5F,0x63,0x6F,0x6C,0x6F,0x72,  /* 000003A0    "as_color" */
+    0x00,0x12,0x05,0x03,0x00,0x00,0x00,0x12,  /* 000003A8    "........" */
+    0x0E,0x02,0x0D,0x62,0x6C,0x65,0x6E,0x64,  /* 000003B0    "...blend" */
+    0x5F,0x65,0x71,0x75,0x00,0x00,0x12,0x0C,  /* 000003B8    "_equ...." */
+    0x02,0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,  /* 000003C0    "..enable" */
+    0x64,0x00,0x01,0x5B,0x82,0x4F,0x06,0x49,  /* 000003C8    "d..[.O.I" */
+    0x44,0x31,0x5F,0x08,0x5F,0x48,0x49,0x44,  /* 000003D0    "D1_._HID" */
+    0x0D,0x50,0x52,0x50,0x30,0x30,0x30,0x30,  /* 000003D8    ".PRP0000" */
+    0x00,0x08,0x5F,0x44,0x53,0x44,0x12,0x45,  /* 000003E0    ".._DSD.E" */
+    0x05,0x02,0x11,0x13,0x0A,0x10,0x14,0xD8,  /* 000003E8    "........" */
+    0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,0x91,  /* 000003F0    "...n.M.." */
+    0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,0x3D,  /* 000003F8    "...J...=" */
+    0x04,0x12,0x07,0x02,0x0D,0x69,0x64,0x00,  /* 00000400    ".....id." */
+    0x01,0x12,0x16,0x02,0x0D,0x63,0x61,0x6E,  /* 00000408    ".....can" */
+    0x76,0x61,0x73,0x5F,0x63,0x6F,0x6C,0x6F,  /* 00000410    "vas_colo" */
+    0x72,0x00,0x12,0x05,0x03,0x00,0x00,0x00,  /* 00000418    "r......." */
+    0x12,0x0E,0x02,0x0D,0x62,0x6C,0x65,0x6E,  /* 00000420    "....blen" */
+    0x64,0x5F,0x65,0x71,0x75,0x00,0x00,0x12,  /* 00000428    "d_equ..." */
+    0x0C,0x02,0x0D,0x65,0x6E,0x61,0x62,0x6C,  /* 00000430    "...enabl" */
+    0x65,0x64,0x00,0x01,0x5B,0x82,0x40,0x07,  /* 00000438    "ed..[.@." */
+    0x49,0x44,0x32,0x5F,0x08,0x5F,0x48,0x49,  /* 00000440    "ID2_._HI" */
+    0x44,0x0D,0x50,0x52,0x50,0x30,0x30,0x30,  /* 00000448    "D.PRP000" */
+    0x30,0x00,0x08,0x5F,0x44,0x53,0x44,0x12,  /* 00000450    "0.._DSD." */
+    0x46,0x05,0x02,0x11,0x13,0x0A,0x10,0x14,  /* 00000458    "F......." */
+    0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,  /* 00000460    "....n.M." */
+    0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,  /* 00000468    "....J..." */
+    0x3E,0x04,0x12,0x08,0x02,0x0D,0x69,0x64,  /* 00000470    ">.....id" */
+    0x00,0x0A,0x02,0x12,0x16,0x02,0x0D,0x63,  /* 00000478    ".......c" */
+    0x61,0x6E,0x76,0x61,0x73,0x5F,0x63,0x6F,  /* 00000480    "anvas_co" */
+    0x6C,0x6F,0x72,0x00,0x12,0x05,0x03,0x00,  /* 00000488    "lor....." */
+    0x00,0x00,0x12,0x0E,0x02,0x0D,0x62,0x6C,  /* 00000490    "......bl" */
+    0x65,0x6E,0x64,0x5F,0x65,0x71,0x75,0x00,  /* 00000498    "end_equ." */
+    0x00,0x12,0x0C,0x02,0x0D,0x65,0x6E,0x61,  /* 000004A0    ".....ena" */
+    0x62,0x6C,0x65,0x64,0x00,0x01,0x5B,0x82,  /* 000004A8    "bled..[." */
+    0x45,0x0E,0x50,0x4C,0x4E,0x53,0x08,0x5F,  /* 000004B0    "E.PLNS._" */
+    0x48,0x49,0x44,0x0D,0x50,0x52,0x50,0x30,  /* 000004B8    "HID.PRP0" */
+    0x30,0x30,0x30,0x00,0x08,0x5F,0x44,0x53,  /* 000004C0    "000.._DS" */
+    0x44,0x12,0x25,0x02,0x11,0x13,0x0A,0x10,  /* 000004C8    "D.%....." */
+    0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,  /* 000004D0    ".....n.M" */
+    0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,  /* 000004D8    ".....J.." */
+    0x12,0x0E,0x01,0x12,0x0B,0x02,0x0D,0x63,  /* 000004E0    ".......c" */
+    0x6F,0x75,0x6E,0x74,0x00,0x0A,0x02,0x5B,  /* 000004E8    "ount...[" */
+    0x82,0x41,0x05,0x50,0x4C,0x30,0x5F,0x08,  /* 000004F0    ".A.PL0_." */
+    0x5F,0x48,0x49,0x44,0x0D,0x50,0x52,0x50,  /* 000004F8    "_HID.PRP" */
+    0x30,0x30,0x30,0x30,0x00,0x08,0x5F,0x44,  /* 00000500    "0000.._D" */
+    0x53,0x44,0x12,0x37,0x02,0x11,0x13,0x0A,  /* 00000508    "SD.7...." */
+    0x10,0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,  /* 00000510    "......n." */
+    0x4D,0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,  /* 00000518    "M.....J." */
+    0x01,0x12,0x20,0x02,0x12,0x0A,0x02,0x0D,  /* 00000520    ".. ....." */
+    0x67,0x61,0x6D,0x6D,0x61,0x00,0x01,0x12,  /* 00000528    "gamma..." */
+    0x12,0x02,0x0D,0x63,0x6F,0x6C,0x6F,0x72,  /* 00000530    "...color" */
+    0x2D,0x6B,0x65,0x79,0x00,0x0C,0xFF,0xFF,  /* 00000538    "-key...." */
+    0xFF,0xFF,0x5B,0x82,0x41,0x05,0x50,0x4C,  /* 00000540    "..[.A.PL" */
+    0x31,0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,  /* 00000548    "1_._HID." */
+    0x50,0x52,0x50,0x30,0x30,0x30,0x30,0x00,  /* 00000550    "PRP0000." */
+    0x08,0x5F,0x44,0x53,0x44,0x12,0x37,0x02,  /* 00000558    "._DSD.7." */
+    0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,  /* 00000560    "........" */
+    0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,  /* 00000568    ".n.M...." */
+    0xBF,0x4A,0xA3,0x01,0x12,0x20,0x02,0x12,  /* 00000570    ".J... .." */
+    0x0A,0x02,0x0D,0x67,0x61,0x6D,0x6D,0x61,  /* 00000578    "...gamma" */
+    0x00,0x00,0x12,0x12,0x02,0x0D,0x63,0x6F,  /* 00000580    "......co" */
+    0x6C,0x6F,0x72,0x2D,0x6B,0x65,0x79,0x00,  /* 00000588    "lor-key." */
+    0x0C,0xFF,0xFF,0xFF,0xFF,0x5B,0x82,0x44,  /* 00000590    ".....[.D" */
+    0x19,0x43,0x4E,0x43,0x54,0x08,0x5F,0x48,  /* 00000598    ".CNCT._H" */
+    0x49,0x44,0x0D,0x50,0x52,0x50,0x30,0x30,  /* 000005A0    "ID.PRP00" */
+    0x30,0x30,0x00,0x08,0x5F,0x44,0x53,0x44,  /* 000005A8    "00.._DSD" */
+    0x12,0x25,0x02,0x11,0x13,0x0A,0x10,0x14,  /* 000005B0    ".%......" */
+    0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,  /* 000005B8    "....n.M." */
+    0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,  /* 000005C0    "....J..." */
+    0x0E,0x01,0x12,0x0B,0x02,0x0D,0x63,0x6F,  /* 000005C8    "......co" */
+    0x75,0x6E,0x74,0x00,0x0A,0x02,0x5B,0x82,  /* 000005D0    "unt...[." */
+    0x4D,0x07,0x43,0x30,0x5F,0x5F,0x08,0x5F,  /* 000005D8    "M.C0__._" */
+    0x48,0x49,0x44,0x0D,0x50,0x52,0x50,0x30,  /* 000005E0    "HID.PRP0" */
+    0x30,0x30,0x30,0x00,0x08,0x5F,0x44,0x53,  /* 000005E8    "000.._DS" */
+    0x44,0x12,0x43,0x06,0x02,0x11,0x13,0x0A,  /* 000005F0    "D.C....." */
+    0x10,0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,  /* 000005F8    "......n." */
+    0x4D,0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,  /* 00000600    "M.....J." */
+    0x01,0x12,0x4B,0x04,0x04,0x12,0x10,0x02,  /* 00000608    "..K....." */
+    0x0D,0x6E,0x61,0x6D,0x65,0x00,0x0D,0x61,  /* 00000610    ".name..a" */
+    0x6E,0x61,0x6C,0x6F,0x67,0x00,0x12,0x0C,  /* 00000618    "nalog..." */
+    0x02,0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,  /* 00000620    "..enable" */
+    0x64,0x00,0x01,0x12,0x14,0x02,0x0D,0x62,  /* 00000628    "d......b" */
+    0x69,0x74,0x73,0x5F,0x70,0x65,0x72,0x5F,  /* 00000630    "its_per_" */
+    0x63,0x6F,0x6C,0x6F,0x72,0x00,0x0A,0x06,  /* 00000638    "color..." */
+    0x12,0x14,0x02,0x0D,0x63,0x6F,0x6E,0x73,  /* 00000640    "....cons" */
+    0x74,0x61,0x6E,0x74,0x5F,0x61,0x6C,0x70,  /* 00000648    "tant_alp" */
+    0x68,0x61,0x00,0x0A,0xFF,0x5B,0x82,0x44,  /* 00000650    "ha...[.D" */
+    0x0D,0x43,0x31,0x5F,0x5F,0x08,0x5F,0x48,  /* 00000658    ".C1__._H" */
+    0x49,0x44,0x0D,0x50,0x52,0x50,0x30,0x30,  /* 00000660    "ID.PRP00" */
+    0x30,0x30,0x00,0x08,0x5F,0x44,0x53,0x44,  /* 00000668    "00.._DSD" */
+    0x12,0x4A,0x0B,0x02,0x11,0x13,0x0A,0x10,  /* 00000670    ".J......" */
+    0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,  /* 00000678    ".....n.M" */
+    0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,  /* 00000680    ".....J.." */
+    0x12,0x42,0x0A,0x07,0x12,0x17,0x02,0x0D,  /* 00000688    ".B......" */
+    0x6E,0x61,0x6D,0x65,0x00,0x0D,0x64,0x69,  /* 00000690    "name..di" */
+    0x73,0x70,0x6C,0x61,0x79,0x70,0x6F,0x72,  /* 00000698    "splaypor" */
+    0x74,0x5F,0x61,0x00,0x12,0x0C,0x02,0x0D,  /* 000006A0    "t_a....." */
+    0x65,0x6E,0x61,0x62,0x6C,0x65,0x64,0x00,  /* 000006A8    "enabled." */
+    0x01,0x12,0x1D,0x02,0x0D,0x73,0x63,0x61,  /* 000006B0    ".....sca" */
+    0x6C,0x69,0x6E,0x67,0x5F,0x6D,0x6F,0x64,  /* 000006B8    "ling_mod" */
+    0x65,0x00,0x0D,0x46,0x75,0x6C,0x6C,0x20,  /* 000006C0    "e..Full " */
+    0x61,0x73,0x70,0x65,0x63,0x74,0x00,0x12,  /* 000006C8    "aspect.." */
+    0x14,0x02,0x0D,0x61,0x75,0x64,0x69,0x6F,  /* 000006D0    "...audio" */
+    0x00,0x0D,0x66,0x6F,0x72,0x63,0x65,0x2D,  /* 000006D8    "..force-" */
+    0x64,0x76,0x69,0x00,0x12,0x1C,0x02,0x0D,  /* 000006E0    "dvi....." */
+    0x42,0x72,0x6F,0x61,0x64,0x63,0x61,0x73,  /* 000006E8    "Broadcas" */
+    0x74,0x5F,0x52,0x47,0x42,0x00,0x0D,0x41,  /* 000006F0    "t_RGB..A" */
+    0x75,0x74,0x6F,0x6D,0x61,0x74,0x69,0x63,  /* 000006F8    "utomatic" */
+    0x00,0x12,0x14,0x02,0x0D,0x62,0x69,0x74,  /* 00000700    ".....bit" */
+    0x73,0x5F,0x70,0x65,0x72,0x5F,0x63,0x6F,  /* 00000708    "s_per_co" */
+    0x6C,0x6F,0x72,0x00,0x0A,0x08,0x12,0x14,  /* 00000710    "lor....." */
+    0x02,0x0D,0x63,0x6F,0x6E,0x73,0x74,0x61,  /* 00000718    "..consta" */
+    0x6E,0x74,0x5F,0x61,0x6C,0x70,0x68,0x61,  /* 00000720    "nt_alpha" */
+    0x00,0x0A,0xFF                            /* 00000728    "..."      */
 };
-- 
2.1.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [RFC 12/12] drm/i915/config: Add ACPI device examples for VBT configuration.
  2015-02-12 23:41 [RFC 00/12] i915 init-time configuration Bob Paauwe
                   ` (10 preceding siblings ...)
  2015-02-12 23:41 ` [RFC 11/12] drm/i915/config: Add workaround properties to ACPI table Bob Paauwe
@ 2015-02-12 23:41 ` Bob Paauwe
  2015-02-13  8:08 ` [RFC 00/12] i915 init-time configuration Jani Nikula
  12 siblings, 0 replies; 32+ messages in thread
From: Bob Paauwe @ 2015-02-12 23:41 UTC (permalink / raw)
  To: intel-gfx

Add VBT device sections with sample data to test the VBT parsing.

Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
---
 drivers/gpu/drm/i915/i915-properties.asl | 140 +++++++
 drivers/gpu/drm/i915/i915-properties.hex | 622 +++++++++++++++++++------------
 2 files changed, 533 insertions(+), 229 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915-properties.asl b/drivers/gpu/drm/i915/i915-properties.asl
index cdd4438..4c5d1e6 100644
--- a/drivers/gpu/drm/i915/i915-properties.asl
+++ b/drivers/gpu/drm/i915/i915-properties.asl
@@ -3,6 +3,9 @@ DefinitionBlock ("i915-properties.aml", "SSDT", 5, "", "", 0x00000001)
 	External (DSEN)
 
 	Device (\_SB.PRP) {
+		Name (_ADR, 0x00020000)
+		Name (_HID, "PRP0000")
+
 		Device(GFX0) {
 		Name (_ADR, 0x00020000)
 		Name (_HID, "PRP0000")
@@ -23,6 +26,143 @@ DefinitionBlock ("i915-properties.aml", "SSDT", 5, "", "", 0x00000001)
 			}
 		})
 
+		// Specify VBT equivelent data. This will override
+		// any firmware supplied configuration.
+		//
+		// VBT is currently split into sections
+		//   general features & definitions
+		//   lvds panel data
+		//   edp panel data
+		//   mipi/dsi panel data (TODO)
+		Device (VBT) {
+			Name (_HID, "PRP0000")
+			Name (_DSD, Package() {
+				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+				Package () {
+					Package () { "internal tv", 1 },
+					Package () { "internal crt", 0 },
+					Package () { "display clock mode,", 0 },
+					Package () { "fdi rx polarity inverted", 0 },
+					Package () { "crt ddc_pin", 2 },
+					Package () { "drrs type", 0 },
+					Package () { "sdvo mappings A", 0x00 },
+					Package () { "sdvo mappings B", 0x00 },
+					//  port info {level shift, support bits}
+					Package () { "port info A", Package () {0x00, 0x0e} },
+					Package () { "port info B", Package () {0x00, 0x01} },
+					Package () { "port info C", Package () {0x00, 0x02} },
+					Package () { "port info D", Package () {0x00, 0x03} },
+					Package () { "port info E", Package () {0x00, 0x04} },
+					// Only one mode?  package is a DTD with:
+					//   hdisplay, hsync_start, hsync_end, htotal,
+					//   vdisplay, vsync_start, vsync_end, vtotal,
+					//   clock, flags
+					// type should be DRM_MODE_TYPE_PREFERRED
+					// flags are h/v sync polarity (see drm_mode.h)
+					Package () { "mode", Package () {800, 810, 820, 820, 600, 610, 620, 620, 0, 0} },
+				}
+			})
+
+			Device (LVDS) {
+				Name (_HID, "PRP0000")
+				Name (_DSD, Package() {
+					ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+					Package () {
+						Package () { "lvds use ssc", 0 },
+						Package () { "lvds ssc freq", 96000 },
+						Package () { "lvds downclock avail", 0 },
+						Package () { "lvds downclock", 0 },
+						Package () { "pixel dither", 0 },
+						Package () { "bios lvds val", 0 },
+					}
+				})
+			}
+
+			Device (EDP) {
+				Name (_HID, "PRP0000")
+				Name (_DSD, Package() {
+					ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+					Package () {
+						Package () { "edp bpp", 0x00 },
+						Package () { "edp rate", 0x00 },
+						Package () { "edp lanes", 0x00 },
+						Package () { "edp preemphasis", 0x00 },
+						Package () { "edp vswing", 0x00 },
+
+						// Alternate way to get timing sequence, see PWSQ
+						// below.
+						Package () { "edp pps",
+							Package () { 0x00, 0x00, 0x00, 0x00, 0x00 }}
+					}
+				})
+
+				// Alternate way to get timing sequence, see edp pps
+				// above.
+				Device (PWSQ) {
+					Name (_HID, "PRP0000")
+					Name (_DSD, Package() {
+						ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+						Package () {
+							Package () { "t1/t3", 1 },
+							Package () { "t8", 0 },
+							Package () { "t9", 0 },
+							Package () { "t10", 0 },
+							Package () { "t11/t12", 0 }
+						}
+					})
+				}
+
+				Device (BKLT) {
+					Name (_HID, "PRP0000")
+					Name (_DSD, Package() {
+						ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+						Package () {
+							Package () { "present", 1 },
+							Package () { "pwm freq hz", 0 },
+							Package () { "active low pwm", 0 },
+							Package () { "min brightness", 0 }
+						}
+					})
+				}
+
+				Device (PSR) {
+					Name (_HID, "PRP0000")
+					Name (_DSD, Package() {
+						ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+						Package () {
+							Package () { "full link", 0x00 },
+							Package () { "require aux wakeup", 0x00 },
+							Package () { "idle frames", 0x00 },
+							Package () { "lines to wait", 0x00 },
+							Package () { "tp1 wakeup time", 0x00 },
+							Package () { "tp2 tp3 wakeup time", 0x00 }
+						}
+					})
+				}
+			}
+
+
+			Device (DSI) {
+				// DSI data is huge.  Is it better to just
+				// use an array for the data?
+				Name (_HID, "PRP0000")
+				Name (_DSD, Package() {
+					ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+					Package () {
+						Package () { "has mipi", 0x00 },
+						Package () { "dsi panel id", 0x00 },
+						Package () { "dsi config", 0x00 },
+						Package () { "dsi pps", 0x00 },
+						Package () { "dsi seq version", 0x00 },
+						Package () { "dsi data", 0x00 },
+						Package () { "dsi size", 0x00 },
+						Package () { "dsi sequence", 0x00 },
+					}
+				})
+			}
+		}
+
+
 		Device (WRKS) {
 			Name (_HID, "PRP0000")
 			Name (_DSD, Package() {
diff --git a/drivers/gpu/drm/i915/i915-properties.hex b/drivers/gpu/drm/i915/i915-properties.hex
index c42c749..6918b39 100644
--- a/drivers/gpu/drm/i915/i915-properties.hex
+++ b/drivers/gpu/drm/i915/i915-properties.hex
@@ -4,242 +4,406 @@
  * ASL+ Optimizing Compiler version 20141107-64 [Dec  2 2014]
  * Copyright (c) 2000 - 2014 Intel Corporation
  * 
- * Compilation of "i915-properties.asl" - Fri Feb  6 14:29:03 2015
+ * Compilation of "i915-properties.asl" - Fri Feb  6 14:30:07 2015
  * 
  * C source code output
- * AML code block contains 0x72B bytes
+ * AML code block contains 0xC4A bytes
  *
  */
 unsigned char AmlCode[] =
 {
-    0x53,0x53,0x44,0x54,0x2B,0x07,0x00,0x00,  /* 00000000    "SSDT+..." */
-    0x05,0x39,0x00,0x00,0x00,0x00,0x00,0x00,  /* 00000008    ".9......" */
+    0x53,0x53,0x44,0x54,0x4A,0x0C,0x00,0x00,  /* 00000000    "SSDTJ..." */
+    0x05,0xF9,0x00,0x00,0x00,0x00,0x00,0x00,  /* 00000008    "........" */
     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  /* 00000010    "........" */
     0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL" */
-    0x07,0x11,0x14,0x20,0x5B,0x82,0x45,0x70,  /* 00000020    "... [.Ep" */
+    0x07,0x11,0x14,0x20,0x5B,0x82,0x44,0xC2,  /* 00000020    "... [.D." */
     0x5C,0x2E,0x5F,0x53,0x42,0x5F,0x50,0x52,  /* 00000028    "\._SB_PR" */
-    0x50,0x5F,0x5B,0x82,0x47,0x6F,0x47,0x46,  /* 00000030    "P_[.GoGF" */
-    0x58,0x30,0x08,0x5F,0x41,0x44,0x52,0x0C,  /* 00000038    "X0._ADR." */
-    0x00,0x00,0x02,0x00,0x08,0x5F,0x48,0x49,  /* 00000040    "....._HI" */
-    0x44,0x0D,0x50,0x52,0x50,0x30,0x30,0x30,  /* 00000048    "D.PRP000" */
-    0x30,0x00,0x14,0x19,0x5F,0x44,0x4F,0x53,  /* 00000050    "0..._DOS" */
-    0x01,0x70,0x7B,0x68,0x0A,0x07,0x00,0x44,  /* 00000058    ".p{h...D" */
-    0x53,0x45,0x4E,0xA0,0x08,0x93,0x7B,0x68,  /* 00000060    "SEN...{h" */
-    0x0A,0x03,0x00,0x00,0x08,0x5F,0x44,0x53,  /* 00000068    "....._DS" */
-    0x44,0x12,0x47,0x05,0x02,0x11,0x13,0x0A,  /* 00000070    "D.G....." */
-    0x10,0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,  /* 00000078    "......n." */
-    0x4D,0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,  /* 00000080    "M.....J." */
-    0x01,0x12,0x3F,0x04,0x12,0x13,0x02,0x0D,  /* 00000088    "..?....." */
-    0x64,0x69,0x73,0x70,0x6C,0x61,0x79,0x5F,  /* 00000090    "display_" */
-    0x64,0x65,0x74,0x65,0x63,0x74,0x00,0x01,  /* 00000098    "detect.." */
-    0x12,0x0D,0x02,0x0D,0x66,0x61,0x73,0x74,  /* 000000A0    "....fast" */
-    0x62,0x6F,0x6F,0x74,0x00,0x01,0x12,0x0E,  /* 000000A8    "boot...." */
-    0x02,0x0D,0x70,0x6F,0x77,0x65,0x72,0x73,  /* 000000B0    "..powers" */
-    0x61,0x76,0x65,0x00,0x00,0x12,0x0B,0x02,  /* 000000B8    "ave....." */
-    0x0D,0x63,0x6F,0x75,0x6E,0x74,0x00,0x0A,  /* 000000C0    ".count.." */
-    0x63,0x5B,0x82,0x4F,0x23,0x57,0x52,0x4B,  /* 000000C8    "c[.O#WRK" */
-    0x53,0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,  /* 000000D0    "S._HID.P" */
-    0x52,0x50,0x30,0x30,0x30,0x30,0x00,0x08,  /* 000000D8    "RP0000.." */
-    0x5F,0x44,0x53,0x44,0x12,0x45,0x22,0x02,  /* 000000E0    "_DSD.E"." */
-    0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,  /* 000000E8    "........" */
-    0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,  /* 000000F0    ".n.M...." */
-    0xBF,0x4A,0xA3,0x01,0x12,0x4D,0x20,0x0C,  /* 000000F8    ".J...M ." */
-    0x12,0x2E,0x02,0x0D,0x57,0x61,0x44,0x69,  /* 00000100    "....WaDi" */
-    0x73,0x61,0x62,0x6C,0x65,0x50,0x61,0x72,  /* 00000108    "sablePar" */
-    0x74,0x69,0x61,0x6C,0x49,0x6E,0x73,0x74,  /* 00000110    "tialInst" */
-    0x53,0x68,0x6F,0x6F,0x74,0x64,0x6F,0x77,  /* 00000118    "Shootdow" */
-    0x6E,0x00,0x12,0x0C,0x04,0x0B,0xF0,0xE4,  /* 00000120    "n......." */
-    0x0B,0x00,0x01,0x0B,0x00,0x01,0x01,0x12,  /* 00000128    "........" */
-    0x31,0x02,0x0D,0x57,0x61,0x44,0x69,0x73,  /* 00000130    "1..WaDis" */
-    0x61,0x62,0x6C,0x65,0x54,0x68,0x72,0x65,  /* 00000138    "ableThre" */
-    0x61,0x64,0x53,0x74,0x61,0x6C,0x6C,0x44,  /* 00000140    "adStallD" */
-    0x6F,0x70,0x43,0x6C,0x6F,0x63,0x6B,0x47,  /* 00000148    "opClockG" */
-    0x61,0x74,0x69,0x6E,0x67,0x00,0x12,0x0A,  /* 00000150    "ating..." */
-    0x04,0x0B,0xF0,0xE4,0x0A,0x20,0x0A,0x20,  /* 00000158    "..... . " */
-    0x01,0x12,0x24,0x02,0x0D,0x57,0x61,0x44,  /* 00000160    "..$..WaD" */
-    0x69,0x73,0x61,0x62,0x6C,0x65,0x44,0x6F,  /* 00000168    "isableDo" */
-    0x70,0x43,0x6C,0x6F,0x63,0x6B,0x47,0x61,  /* 00000170    "pClockGa" */
-    0x74,0x69,0x6E,0x67,0x00,0x12,0x08,0x04,  /* 00000178    "ting...." */
-    0x0B,0xF4,0xE4,0x01,0x01,0x01,0x12,0x2A,  /* 00000180    ".......*" */
-    0x02,0x0D,0x57,0x61,0x44,0x69,0x73,0x61,  /* 00000188    "..WaDisa" */
-    0x62,0x6C,0x65,0x53,0x61,0x6D,0x70,0x6C,  /* 00000190    "bleSampl" */
-    0x65,0x72,0x50,0x6F,0x77,0x65,0x72,0x42,  /* 00000198    "erPowerB" */
-    0x79,0x70,0x61,0x73,0x73,0x00,0x12,0x0A,  /* 000001A0    "ypass..." */
-    0x04,0x0B,0x84,0xE1,0x0A,0x02,0x0A,0x02,  /* 000001A8    "........" */
-    0x01,0x12,0x2E,0x02,0x0D,0x57,0x61,0x44,  /* 000001B0    ".....WaD" */
-    0x69,0x73,0x61,0x62,0x6C,0x65,0x50,0x61,  /* 000001B8    "isablePa" */
-    0x72,0x74,0x69,0x61,0x6C,0x49,0x6E,0x73,  /* 000001C0    "rtialIns" */
-    0x74,0x53,0x68,0x6F,0x6F,0x74,0x64,0x6F,  /* 000001C8    "tShootdo" */
-    0x77,0x6E,0x00,0x12,0x0C,0x04,0x0B,0xF0,  /* 000001D0    "wn......" */
-    0xE4,0x0B,0x00,0x01,0x0B,0x00,0x01,0x01,  /* 000001D8    "........" */
-    0x12,0x31,0x02,0x0D,0x57,0x61,0x44,0x69,  /* 000001E0    ".1..WaDi" */
-    0x73,0x61,0x62,0x6C,0x65,0x54,0x68,0x72,  /* 000001E8    "sableThr" */
-    0x65,0x61,0x64,0x53,0x74,0x61,0x6C,0x6C,  /* 000001F0    "eadStall" */
-    0x44,0x6F,0x70,0x43,0x6C,0x6F,0x63,0x6B,  /* 000001F8    "DopClock" */
-    0x47,0x61,0x74,0x69,0x6E,0x67,0x00,0x12,  /* 00000200    "Gating.." */
-    0x0A,0x04,0x0B,0xF0,0xE4,0x0A,0x20,0x0A,  /* 00000208    "...... ." */
-    0x20,0x01,0x12,0x24,0x02,0x0D,0x57,0x61,  /* 00000210    " ..$..Wa" */
-    0x44,0x69,0x73,0x61,0x62,0x6C,0x65,0x44,  /* 00000218    "DisableD" */
-    0x6F,0x70,0x43,0x6C,0x6F,0x63,0x6B,0x47,  /* 00000220    "opClockG" */
-    0x61,0x74,0x69,0x6E,0x67,0x00,0x12,0x08,  /* 00000228    "ating..." */
-    0x04,0x0B,0xF4,0xE4,0x01,0x01,0x01,0x12,  /* 00000230    "........" */
-    0x26,0x02,0x0D,0x57,0x61,0x44,0x69,0x73,  /* 00000238    "&..WaDis" */
-    0x61,0x62,0x6C,0x65,0x44,0x6F,0x70,0x43,  /* 00000240    "ableDopC" */
-    0x6C,0x6F,0x63,0x6B,0x47,0x61,0x74,0x69,  /* 00000248    "lockGati" */
-    0x6E,0x67,0x00,0x12,0x0A,0x04,0x0B,0x84,  /* 00000250    "ng......" */
-    0xE1,0x0A,0x02,0x0A,0x02,0x01,0x12,0x2D,  /* 00000258    ".......-" */
-    0x02,0x0D,0x57,0x61,0x44,0x69,0x73,0x61,  /* 00000260    "..WaDisa" */
-    0x62,0x6C,0x65,0x46,0x65,0x6E,0x63,0x65,  /* 00000268    "bleFence" */
-    0x44,0x65,0x73,0x74,0x69,0x6E,0x61,0x74,  /* 00000270    "Destinat" */
-    0x69,0x6F,0x6E,0x54,0x6F,0x53,0x4C,0x4D,  /* 00000278    "ionToSLM" */
-    0x00,0x12,0x0A,0x04,0x0B,0x00,0x73,0x0A,  /* 00000280    "......s." */
-    0x10,0x0A,0x10,0x01,0x12,0x33,0x02,0x0D,  /* 00000288    ".....3.." */
-    0x57,0x61,0x44,0x69,0x73,0x61,0x62,0x6C,  /* 00000290    "WaDisabl" */
-    0x65,0x46,0x65,0x6E,0x63,0x65,0x44,0x65,  /* 00000298    "eFenceDe" */
-    0x73,0x74,0x69,0x6E,0x61,0x74,0x69,0x6F,  /* 000002A0    "stinatio" */
-    0x6E,0x54,0x6F,0x53,0x4C,0x4D,0x20,0x47,  /* 000002A8    "nToSLM G" */
-    0x54,0x33,0x00,0x12,0x0C,0x04,0x0B,0x00,  /* 000002B0    "T3......" */
-    0x73,0x0B,0x00,0x40,0x0B,0x00,0x40,0x01,  /* 000002B8    "s..@..@." */
-    0x12,0x2A,0x02,0x0D,0x57,0x61,0x34,0x78,  /* 000002C0    ".*..Wa4x" */
-    0x34,0x53,0x54,0x43,0x4F,0x70,0x74,0x69,  /* 000002C8    "4STCOpti" */
-    0x6D,0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,  /* 000002D0    "mization" */
-    0x44,0x69,0x73,0x61,0x62,0x6C,0x65,0x00,  /* 000002D8    "Disable." */
-    0x12,0x0A,0x04,0x0B,0x04,0x70,0x0A,0x40,  /* 000002E0    ".....p.@" */
-    0x0A,0x40,0x01,0x12,0x1E,0x02,0x0D,0x57,  /* 000002E8    ".@.....W" */
-    0x61,0x31,0x36,0x78,0x34,0x68,0x61,0x73,  /* 000002F0    "a16x4has" */
-    0x68,0x69,0x6E,0x67,0x00,0x12,0x0C,0x04,  /* 000002F8    "hing...." */
-    0x0B,0x08,0x70,0x0B,0x00,0x02,0x0B,0x80,  /* 00000300    "..p....." */
-    0x02,0x01,0x5B,0x82,0x42,0x1A,0x43,0x52,  /* 00000308    "..[.B.CR" */
-    0x54,0x43,0x08,0x5F,0x48,0x49,0x44,0x0D,  /* 00000310    "TC._HID." */
-    0x50,0x52,0x50,0x30,0x30,0x30,0x30,0x00,  /* 00000318    "PRP0000." */
-    0x08,0x5F,0x44,0x53,0x44,0x12,0x34,0x02,  /* 00000320    "._DSD.4." */
-    0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,  /* 00000328    "........" */
-    0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,  /* 00000330    ".n.M...." */
-    0xBF,0x4A,0xA3,0x01,0x12,0x1D,0x02,0x12,  /* 00000338    ".J......" */
-    0x0E,0x02,0x0D,0x65,0x6E,0x61,0x62,0x6C,  /* 00000340    "...enabl" */
-    0x65,0x64,0x00,0x0D,0x33,0x00,0x12,0x0B,  /* 00000348    "ed..3..." */
-    0x02,0x0D,0x63,0x6F,0x75,0x6E,0x74,0x00,  /* 00000350    "..count." */
-    0x0A,0x03,0x5B,0x82,0x4F,0x06,0x49,0x44,  /* 00000358    "..[.O.ID" */
-    0x30,0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,  /* 00000360    "0_._HID." */
-    0x50,0x52,0x50,0x30,0x30,0x30,0x30,0x00,  /* 00000368    "PRP0000." */
-    0x08,0x5F,0x44,0x53,0x44,0x12,0x45,0x05,  /* 00000370    "._DSD.E." */
-    0x02,0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,  /* 00000378    "........" */
-    0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,  /* 00000380    "..n.M..." */
-    0x9B,0xBF,0x4A,0xA3,0x01,0x12,0x3D,0x04,  /* 00000388    "..J...=." */
-    0x12,0x07,0x02,0x0D,0x69,0x64,0x00,0x00,  /* 00000390    "....id.." */
-    0x12,0x16,0x02,0x0D,0x63,0x61,0x6E,0x76,  /* 00000398    "....canv" */
-    0x61,0x73,0x5F,0x63,0x6F,0x6C,0x6F,0x72,  /* 000003A0    "as_color" */
-    0x00,0x12,0x05,0x03,0x00,0x00,0x00,0x12,  /* 000003A8    "........" */
-    0x0E,0x02,0x0D,0x62,0x6C,0x65,0x6E,0x64,  /* 000003B0    "...blend" */
-    0x5F,0x65,0x71,0x75,0x00,0x00,0x12,0x0C,  /* 000003B8    "_equ...." */
-    0x02,0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,  /* 000003C0    "..enable" */
-    0x64,0x00,0x01,0x5B,0x82,0x4F,0x06,0x49,  /* 000003C8    "d..[.O.I" */
-    0x44,0x31,0x5F,0x08,0x5F,0x48,0x49,0x44,  /* 000003D0    "D1_._HID" */
-    0x0D,0x50,0x52,0x50,0x30,0x30,0x30,0x30,  /* 000003D8    ".PRP0000" */
-    0x00,0x08,0x5F,0x44,0x53,0x44,0x12,0x45,  /* 000003E0    ".._DSD.E" */
-    0x05,0x02,0x11,0x13,0x0A,0x10,0x14,0xD8,  /* 000003E8    "........" */
-    0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,0x91,  /* 000003F0    "...n.M.." */
-    0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,0x3D,  /* 000003F8    "...J...=" */
-    0x04,0x12,0x07,0x02,0x0D,0x69,0x64,0x00,  /* 00000400    ".....id." */
-    0x01,0x12,0x16,0x02,0x0D,0x63,0x61,0x6E,  /* 00000408    ".....can" */
-    0x76,0x61,0x73,0x5F,0x63,0x6F,0x6C,0x6F,  /* 00000410    "vas_colo" */
-    0x72,0x00,0x12,0x05,0x03,0x00,0x00,0x00,  /* 00000418    "r......." */
-    0x12,0x0E,0x02,0x0D,0x62,0x6C,0x65,0x6E,  /* 00000420    "....blen" */
-    0x64,0x5F,0x65,0x71,0x75,0x00,0x00,0x12,  /* 00000428    "d_equ..." */
-    0x0C,0x02,0x0D,0x65,0x6E,0x61,0x62,0x6C,  /* 00000430    "...enabl" */
-    0x65,0x64,0x00,0x01,0x5B,0x82,0x40,0x07,  /* 00000438    "ed..[.@." */
-    0x49,0x44,0x32,0x5F,0x08,0x5F,0x48,0x49,  /* 00000440    "ID2_._HI" */
-    0x44,0x0D,0x50,0x52,0x50,0x30,0x30,0x30,  /* 00000448    "D.PRP000" */
-    0x30,0x00,0x08,0x5F,0x44,0x53,0x44,0x12,  /* 00000450    "0.._DSD." */
-    0x46,0x05,0x02,0x11,0x13,0x0A,0x10,0x14,  /* 00000458    "F......." */
-    0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,  /* 00000460    "....n.M." */
-    0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,  /* 00000468    "....J..." */
-    0x3E,0x04,0x12,0x08,0x02,0x0D,0x69,0x64,  /* 00000470    ">.....id" */
-    0x00,0x0A,0x02,0x12,0x16,0x02,0x0D,0x63,  /* 00000478    ".......c" */
-    0x61,0x6E,0x76,0x61,0x73,0x5F,0x63,0x6F,  /* 00000480    "anvas_co" */
-    0x6C,0x6F,0x72,0x00,0x12,0x05,0x03,0x00,  /* 00000488    "lor....." */
-    0x00,0x00,0x12,0x0E,0x02,0x0D,0x62,0x6C,  /* 00000490    "......bl" */
-    0x65,0x6E,0x64,0x5F,0x65,0x71,0x75,0x00,  /* 00000498    "end_equ." */
-    0x00,0x12,0x0C,0x02,0x0D,0x65,0x6E,0x61,  /* 000004A0    ".....ena" */
-    0x62,0x6C,0x65,0x64,0x00,0x01,0x5B,0x82,  /* 000004A8    "bled..[." */
-    0x45,0x0E,0x50,0x4C,0x4E,0x53,0x08,0x5F,  /* 000004B0    "E.PLNS._" */
-    0x48,0x49,0x44,0x0D,0x50,0x52,0x50,0x30,  /* 000004B8    "HID.PRP0" */
-    0x30,0x30,0x30,0x00,0x08,0x5F,0x44,0x53,  /* 000004C0    "000.._DS" */
-    0x44,0x12,0x25,0x02,0x11,0x13,0x0A,0x10,  /* 000004C8    "D.%....." */
-    0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,  /* 000004D0    ".....n.M" */
-    0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,  /* 000004D8    ".....J.." */
-    0x12,0x0E,0x01,0x12,0x0B,0x02,0x0D,0x63,  /* 000004E0    ".......c" */
-    0x6F,0x75,0x6E,0x74,0x00,0x0A,0x02,0x5B,  /* 000004E8    "ount...[" */
-    0x82,0x41,0x05,0x50,0x4C,0x30,0x5F,0x08,  /* 000004F0    ".A.PL0_." */
-    0x5F,0x48,0x49,0x44,0x0D,0x50,0x52,0x50,  /* 000004F8    "_HID.PRP" */
-    0x30,0x30,0x30,0x30,0x00,0x08,0x5F,0x44,  /* 00000500    "0000.._D" */
-    0x53,0x44,0x12,0x37,0x02,0x11,0x13,0x0A,  /* 00000508    "SD.7...." */
-    0x10,0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,  /* 00000510    "......n." */
-    0x4D,0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,  /* 00000518    "M.....J." */
-    0x01,0x12,0x20,0x02,0x12,0x0A,0x02,0x0D,  /* 00000520    ".. ....." */
-    0x67,0x61,0x6D,0x6D,0x61,0x00,0x01,0x12,  /* 00000528    "gamma..." */
-    0x12,0x02,0x0D,0x63,0x6F,0x6C,0x6F,0x72,  /* 00000530    "...color" */
-    0x2D,0x6B,0x65,0x79,0x00,0x0C,0xFF,0xFF,  /* 00000538    "-key...." */
-    0xFF,0xFF,0x5B,0x82,0x41,0x05,0x50,0x4C,  /* 00000540    "..[.A.PL" */
-    0x31,0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,  /* 00000548    "1_._HID." */
-    0x50,0x52,0x50,0x30,0x30,0x30,0x30,0x00,  /* 00000550    "PRP0000." */
-    0x08,0x5F,0x44,0x53,0x44,0x12,0x37,0x02,  /* 00000558    "._DSD.7." */
-    0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,  /* 00000560    "........" */
-    0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,  /* 00000568    ".n.M...." */
-    0xBF,0x4A,0xA3,0x01,0x12,0x20,0x02,0x12,  /* 00000570    ".J... .." */
-    0x0A,0x02,0x0D,0x67,0x61,0x6D,0x6D,0x61,  /* 00000578    "...gamma" */
-    0x00,0x00,0x12,0x12,0x02,0x0D,0x63,0x6F,  /* 00000580    "......co" */
-    0x6C,0x6F,0x72,0x2D,0x6B,0x65,0x79,0x00,  /* 00000588    "lor-key." */
-    0x0C,0xFF,0xFF,0xFF,0xFF,0x5B,0x82,0x44,  /* 00000590    ".....[.D" */
-    0x19,0x43,0x4E,0x43,0x54,0x08,0x5F,0x48,  /* 00000598    ".CNCT._H" */
-    0x49,0x44,0x0D,0x50,0x52,0x50,0x30,0x30,  /* 000005A0    "ID.PRP00" */
-    0x30,0x30,0x00,0x08,0x5F,0x44,0x53,0x44,  /* 000005A8    "00.._DSD" */
-    0x12,0x25,0x02,0x11,0x13,0x0A,0x10,0x14,  /* 000005B0    ".%......" */
-    0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,  /* 000005B8    "....n.M." */
-    0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,  /* 000005C0    "....J..." */
-    0x0E,0x01,0x12,0x0B,0x02,0x0D,0x63,0x6F,  /* 000005C8    "......co" */
-    0x75,0x6E,0x74,0x00,0x0A,0x02,0x5B,0x82,  /* 000005D0    "unt...[." */
-    0x4D,0x07,0x43,0x30,0x5F,0x5F,0x08,0x5F,  /* 000005D8    "M.C0__._" */
-    0x48,0x49,0x44,0x0D,0x50,0x52,0x50,0x30,  /* 000005E0    "HID.PRP0" */
-    0x30,0x30,0x30,0x00,0x08,0x5F,0x44,0x53,  /* 000005E8    "000.._DS" */
-    0x44,0x12,0x43,0x06,0x02,0x11,0x13,0x0A,  /* 000005F0    "D.C....." */
-    0x10,0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,  /* 000005F8    "......n." */
-    0x4D,0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,  /* 00000600    "M.....J." */
-    0x01,0x12,0x4B,0x04,0x04,0x12,0x10,0x02,  /* 00000608    "..K....." */
-    0x0D,0x6E,0x61,0x6D,0x65,0x00,0x0D,0x61,  /* 00000610    ".name..a" */
-    0x6E,0x61,0x6C,0x6F,0x67,0x00,0x12,0x0C,  /* 00000618    "nalog..." */
-    0x02,0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,  /* 00000620    "..enable" */
-    0x64,0x00,0x01,0x12,0x14,0x02,0x0D,0x62,  /* 00000628    "d......b" */
-    0x69,0x74,0x73,0x5F,0x70,0x65,0x72,0x5F,  /* 00000630    "its_per_" */
-    0x63,0x6F,0x6C,0x6F,0x72,0x00,0x0A,0x06,  /* 00000638    "color..." */
-    0x12,0x14,0x02,0x0D,0x63,0x6F,0x6E,0x73,  /* 00000640    "....cons" */
-    0x74,0x61,0x6E,0x74,0x5F,0x61,0x6C,0x70,  /* 00000648    "tant_alp" */
-    0x68,0x61,0x00,0x0A,0xFF,0x5B,0x82,0x44,  /* 00000650    "ha...[.D" */
-    0x0D,0x43,0x31,0x5F,0x5F,0x08,0x5F,0x48,  /* 00000658    ".C1__._H" */
-    0x49,0x44,0x0D,0x50,0x52,0x50,0x30,0x30,  /* 00000660    "ID.PRP00" */
-    0x30,0x30,0x00,0x08,0x5F,0x44,0x53,0x44,  /* 00000668    "00.._DSD" */
-    0x12,0x4A,0x0B,0x02,0x11,0x13,0x0A,0x10,  /* 00000670    ".J......" */
-    0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,  /* 00000678    ".....n.M" */
-    0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,  /* 00000680    ".....J.." */
-    0x12,0x42,0x0A,0x07,0x12,0x17,0x02,0x0D,  /* 00000688    ".B......" */
-    0x6E,0x61,0x6D,0x65,0x00,0x0D,0x64,0x69,  /* 00000690    "name..di" */
-    0x73,0x70,0x6C,0x61,0x79,0x70,0x6F,0x72,  /* 00000698    "splaypor" */
-    0x74,0x5F,0x61,0x00,0x12,0x0C,0x02,0x0D,  /* 000006A0    "t_a....." */
-    0x65,0x6E,0x61,0x62,0x6C,0x65,0x64,0x00,  /* 000006A8    "enabled." */
-    0x01,0x12,0x1D,0x02,0x0D,0x73,0x63,0x61,  /* 000006B0    ".....sca" */
-    0x6C,0x69,0x6E,0x67,0x5F,0x6D,0x6F,0x64,  /* 000006B8    "ling_mod" */
-    0x65,0x00,0x0D,0x46,0x75,0x6C,0x6C,0x20,  /* 000006C0    "e..Full " */
-    0x61,0x73,0x70,0x65,0x63,0x74,0x00,0x12,  /* 000006C8    "aspect.." */
-    0x14,0x02,0x0D,0x61,0x75,0x64,0x69,0x6F,  /* 000006D0    "...audio" */
-    0x00,0x0D,0x66,0x6F,0x72,0x63,0x65,0x2D,  /* 000006D8    "..force-" */
-    0x64,0x76,0x69,0x00,0x12,0x1C,0x02,0x0D,  /* 000006E0    "dvi....." */
-    0x42,0x72,0x6F,0x61,0x64,0x63,0x61,0x73,  /* 000006E8    "Broadcas" */
-    0x74,0x5F,0x52,0x47,0x42,0x00,0x0D,0x41,  /* 000006F0    "t_RGB..A" */
-    0x75,0x74,0x6F,0x6D,0x61,0x74,0x69,0x63,  /* 000006F8    "utomatic" */
-    0x00,0x12,0x14,0x02,0x0D,0x62,0x69,0x74,  /* 00000700    ".....bit" */
-    0x73,0x5F,0x70,0x65,0x72,0x5F,0x63,0x6F,  /* 00000708    "s_per_co" */
-    0x6C,0x6F,0x72,0x00,0x0A,0x08,0x12,0x14,  /* 00000710    "lor....." */
-    0x02,0x0D,0x63,0x6F,0x6E,0x73,0x74,0x61,  /* 00000718    "..consta" */
-    0x6E,0x74,0x5F,0x61,0x6C,0x70,0x68,0x61,  /* 00000720    "nt_alpha" */
-    0x00,0x0A,0xFF                            /* 00000728    "..."      */
+    0x50,0x5F,0x08,0x5F,0x41,0x44,0x52,0x0C,  /* 00000030    "P_._ADR." */
+    0x00,0x00,0x02,0x00,0x08,0x5F,0x48,0x49,  /* 00000038    "....._HI" */
+    0x44,0x0D,0x50,0x52,0x50,0x30,0x30,0x30,  /* 00000040    "D.PRP000" */
+    0x30,0x00,0x5B,0x82,0x4E,0xBF,0x47,0x46,  /* 00000048    "0.[.N.GF" */
+    0x58,0x30,0x08,0x5F,0x41,0x44,0x52,0x0C,  /* 00000050    "X0._ADR." */
+    0x00,0x00,0x02,0x00,0x08,0x5F,0x48,0x49,  /* 00000058    "....._HI" */
+    0x44,0x0D,0x50,0x52,0x50,0x30,0x30,0x30,  /* 00000060    "D.PRP000" */
+    0x30,0x00,0x14,0x19,0x5F,0x44,0x4F,0x53,  /* 00000068    "0..._DOS" */
+    0x01,0x70,0x7B,0x68,0x0A,0x07,0x00,0x44,  /* 00000070    ".p{h...D" */
+    0x53,0x45,0x4E,0xA0,0x08,0x93,0x7B,0x68,  /* 00000078    "SEN...{h" */
+    0x0A,0x03,0x00,0x00,0x08,0x5F,0x44,0x53,  /* 00000080    "....._DS" */
+    0x44,0x12,0x47,0x05,0x02,0x11,0x13,0x0A,  /* 00000088    "D.G....." */
+    0x10,0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,  /* 00000090    "......n." */
+    0x4D,0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,  /* 00000098    "M.....J." */
+    0x01,0x12,0x3F,0x04,0x12,0x13,0x02,0x0D,  /* 000000A0    "..?....." */
+    0x64,0x69,0x73,0x70,0x6C,0x61,0x79,0x5F,  /* 000000A8    "display_" */
+    0x64,0x65,0x74,0x65,0x63,0x74,0x00,0x01,  /* 000000B0    "detect.." */
+    0x12,0x0D,0x02,0x0D,0x66,0x61,0x73,0x74,  /* 000000B8    "....fast" */
+    0x62,0x6F,0x6F,0x74,0x00,0x01,0x12,0x0E,  /* 000000C0    "boot...." */
+    0x02,0x0D,0x70,0x6F,0x77,0x65,0x72,0x73,  /* 000000C8    "..powers" */
+    0x61,0x76,0x65,0x00,0x00,0x12,0x0B,0x02,  /* 000000D0    "ave....." */
+    0x0D,0x63,0x6F,0x75,0x6E,0x74,0x00,0x0A,  /* 000000D8    ".count.." */
+    0x63,0x5B,0x82,0x45,0x50,0x56,0x42,0x54,  /* 000000E0    "c[.EPVBT" */
+    0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,  /* 000000E8    "_._HID.P" */
+    0x52,0x50,0x30,0x30,0x30,0x30,0x00,0x08,  /* 000000F0    "RP0000.." */
+    0x5F,0x44,0x53,0x44,0x12,0x43,0x15,0x02,  /* 000000F8    "_DSD.C.." */
+    0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,  /* 00000100    "........" */
+    0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,  /* 00000108    ".n.M...." */
+    0xBF,0x4A,0xA3,0x01,0x12,0x4B,0x13,0x0E,  /* 00000110    ".J...K.." */
+    0x12,0x10,0x02,0x0D,0x69,0x6E,0x74,0x65,  /* 00000118    "....inte" */
+    0x72,0x6E,0x61,0x6C,0x20,0x74,0x76,0x00,  /* 00000120    "rnal tv." */
+    0x01,0x12,0x11,0x02,0x0D,0x69,0x6E,0x74,  /* 00000128    ".....int" */
+    0x65,0x72,0x6E,0x61,0x6C,0x20,0x63,0x72,  /* 00000130    "ernal cr" */
+    0x74,0x00,0x00,0x12,0x18,0x02,0x0D,0x64,  /* 00000138    "t......d" */
+    0x69,0x73,0x70,0x6C,0x61,0x79,0x20,0x63,  /* 00000140    "isplay c" */
+    0x6C,0x6F,0x63,0x6B,0x20,0x6D,0x6F,0x64,  /* 00000148    "lock mod" */
+    0x65,0x2C,0x00,0x00,0x12,0x1D,0x02,0x0D,  /* 00000150    "e,......" */
+    0x66,0x64,0x69,0x20,0x72,0x78,0x20,0x70,  /* 00000158    "fdi rx p" */
+    0x6F,0x6C,0x61,0x72,0x69,0x74,0x79,0x20,  /* 00000160    "olarity " */
+    0x69,0x6E,0x76,0x65,0x72,0x74,0x65,0x64,  /* 00000168    "inverted" */
+    0x00,0x00,0x12,0x11,0x02,0x0D,0x63,0x72,  /* 00000170    "......cr" */
+    0x74,0x20,0x64,0x64,0x63,0x5F,0x70,0x69,  /* 00000178    "t ddc_pi" */
+    0x6E,0x00,0x0A,0x02,0x12,0x0E,0x02,0x0D,  /* 00000180    "n......." */
+    0x64,0x72,0x72,0x73,0x20,0x74,0x79,0x70,  /* 00000188    "drrs typ" */
+    0x65,0x00,0x00,0x12,0x14,0x02,0x0D,0x73,  /* 00000190    "e......s" */
+    0x64,0x76,0x6F,0x20,0x6D,0x61,0x70,0x70,  /* 00000198    "dvo mapp" */
+    0x69,0x6E,0x67,0x73,0x20,0x41,0x00,0x00,  /* 000001A0    "ings A.." */
+    0x12,0x14,0x02,0x0D,0x73,0x64,0x76,0x6F,  /* 000001A8    "....sdvo" */
+    0x20,0x6D,0x61,0x70,0x70,0x69,0x6E,0x67,  /* 000001B0    " mapping" */
+    0x73,0x20,0x42,0x00,0x00,0x12,0x15,0x02,  /* 000001B8    "s B....." */
+    0x0D,0x70,0x6F,0x72,0x74,0x20,0x69,0x6E,  /* 000001C0    ".port in" */
+    0x66,0x6F,0x20,0x41,0x00,0x12,0x05,0x02,  /* 000001C8    "fo A...." */
+    0x00,0x0A,0x0E,0x12,0x14,0x02,0x0D,0x70,  /* 000001D0    ".......p" */
+    0x6F,0x72,0x74,0x20,0x69,0x6E,0x66,0x6F,  /* 000001D8    "ort info" */
+    0x20,0x42,0x00,0x12,0x04,0x02,0x00,0x01,  /* 000001E0    " B......" */
+    0x12,0x15,0x02,0x0D,0x70,0x6F,0x72,0x74,  /* 000001E8    "....port" */
+    0x20,0x69,0x6E,0x66,0x6F,0x20,0x43,0x00,  /* 000001F0    " info C." */
+    0x12,0x05,0x02,0x00,0x0A,0x02,0x12,0x15,  /* 000001F8    "........" */
+    0x02,0x0D,0x70,0x6F,0x72,0x74,0x20,0x69,  /* 00000200    "..port i" */
+    0x6E,0x66,0x6F,0x20,0x44,0x00,0x12,0x05,  /* 00000208    "nfo D..." */
+    0x02,0x00,0x0A,0x03,0x12,0x15,0x02,0x0D,  /* 00000210    "........" */
+    0x70,0x6F,0x72,0x74,0x20,0x69,0x6E,0x66,  /* 00000218    "port inf" */
+    0x6F,0x20,0x45,0x00,0x12,0x05,0x02,0x00,  /* 00000220    "o E....." */
+    0x0A,0x04,0x12,0x25,0x02,0x0D,0x6D,0x6F,  /* 00000228    "...%..mo" */
+    0x64,0x65,0x00,0x12,0x1C,0x0A,0x0B,0x20,  /* 00000230    "de..... " */
+    0x03,0x0B,0x2A,0x03,0x0B,0x34,0x03,0x0B,  /* 00000238    "..*..4.." */
+    0x34,0x03,0x0B,0x58,0x02,0x0B,0x62,0x02,  /* 00000240    "4..X..b." */
+    0x0B,0x6C,0x02,0x0B,0x6C,0x02,0x00,0x00,  /* 00000248    ".l..l..." */
+    0x5B,0x82,0x41,0x0B,0x4C,0x56,0x44,0x53,  /* 00000250    "[.A.LVDS" */
+    0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,0x52,  /* 00000258    "._HID.PR" */
+    0x50,0x30,0x30,0x30,0x30,0x00,0x08,0x5F,  /* 00000260    "P0000.._" */
+    0x44,0x53,0x44,0x12,0x47,0x09,0x02,0x11,  /* 00000268    "DSD.G..." */
+    0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,0xBA,  /* 00000270    "........" */
+    0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,0xBF,  /* 00000278    "n.M....." */
+    0x4A,0xA3,0x01,0x12,0x4F,0x07,0x06,0x12,  /* 00000280    "J...O..." */
+    0x11,0x02,0x0D,0x6C,0x76,0x64,0x73,0x20,  /* 00000288    "...lvds " */
+    0x75,0x73,0x65,0x20,0x73,0x73,0x63,0x00,  /* 00000290    "use ssc." */
+    0x00,0x12,0x16,0x02,0x0D,0x6C,0x76,0x64,  /* 00000298    ".....lvd" */
+    0x73,0x20,0x73,0x73,0x63,0x20,0x66,0x72,  /* 000002A0    "s ssc fr" */
+    0x65,0x71,0x00,0x0C,0x00,0x77,0x01,0x00,  /* 000002A8    "eq...w.." */
+    0x12,0x19,0x02,0x0D,0x6C,0x76,0x64,0x73,  /* 000002B0    "....lvds" */
+    0x20,0x64,0x6F,0x77,0x6E,0x63,0x6C,0x6F,  /* 000002B8    " downclo" */
+    0x63,0x6B,0x20,0x61,0x76,0x61,0x69,0x6C,  /* 000002C0    "ck avail" */
+    0x00,0x00,0x12,0x13,0x02,0x0D,0x6C,0x76,  /* 000002C8    "......lv" */
+    0x64,0x73,0x20,0x64,0x6F,0x77,0x6E,0x63,  /* 000002D0    "ds downc" */
+    0x6C,0x6F,0x63,0x6B,0x00,0x00,0x12,0x11,  /* 000002D8    "lock...." */
+    0x02,0x0D,0x70,0x69,0x78,0x65,0x6C,0x20,  /* 000002E0    "..pixel " */
+    0x64,0x69,0x74,0x68,0x65,0x72,0x00,0x00,  /* 000002E8    "dither.." */
+    0x12,0x12,0x02,0x0D,0x62,0x69,0x6F,0x73,  /* 000002F0    "....bios" */
+    0x20,0x6C,0x76,0x64,0x73,0x20,0x76,0x61,  /* 000002F8    " lvds va" */
+    0x6C,0x00,0x00,0x5B,0x82,0x4C,0x22,0x45,  /* 00000300    "l..[.L"E" */
+    0x44,0x50,0x5F,0x08,0x5F,0x48,0x49,0x44,  /* 00000308    "DP_._HID" */
+    0x0D,0x50,0x52,0x50,0x30,0x30,0x30,0x30,  /* 00000310    ".PRP0000" */
+    0x00,0x08,0x5F,0x44,0x53,0x44,0x12,0x4E,  /* 00000318    ".._DSD.N" */
+    0x07,0x02,0x11,0x13,0x0A,0x10,0x14,0xD8,  /* 00000320    "........" */
+    0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,0x91,  /* 00000328    "...n.M.." */
+    0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,0x46,  /* 00000330    "...J...F" */
+    0x06,0x06,0x12,0x0C,0x02,0x0D,0x65,0x64,  /* 00000338    "......ed" */
+    0x70,0x20,0x62,0x70,0x70,0x00,0x00,0x12,  /* 00000340    "p bpp..." */
+    0x0D,0x02,0x0D,0x65,0x64,0x70,0x20,0x72,  /* 00000348    "...edp r" */
+    0x61,0x74,0x65,0x00,0x00,0x12,0x0E,0x02,  /* 00000350    "ate....." */
+    0x0D,0x65,0x64,0x70,0x20,0x6C,0x61,0x6E,  /* 00000358    ".edp lan" */
+    0x65,0x73,0x00,0x00,0x12,0x14,0x02,0x0D,  /* 00000360    "es......" */
+    0x65,0x64,0x70,0x20,0x70,0x72,0x65,0x65,  /* 00000368    "edp pree" */
+    0x6D,0x70,0x68,0x61,0x73,0x69,0x73,0x00,  /* 00000370    "mphasis." */
+    0x00,0x12,0x0F,0x02,0x0D,0x65,0x64,0x70,  /* 00000378    ".....edp" */
+    0x20,0x76,0x73,0x77,0x69,0x6E,0x67,0x00,  /* 00000380    " vswing." */
+    0x00,0x12,0x13,0x02,0x0D,0x65,0x64,0x70,  /* 00000388    ".....edp" */
+    0x20,0x70,0x70,0x73,0x00,0x12,0x07,0x05,  /* 00000390    " pps...." */
+    0x00,0x00,0x00,0x00,0x00,0x5B,0x82,0x45,  /* 00000398    ".....[.E" */
+    0x06,0x50,0x57,0x53,0x51,0x08,0x5F,0x48,  /* 000003A0    ".PWSQ._H" */
+    0x49,0x44,0x0D,0x50,0x52,0x50,0x30,0x30,  /* 000003A8    "ID.PRP00" */
+    0x30,0x30,0x00,0x08,0x5F,0x44,0x53,0x44,  /* 000003B0    "00.._DSD" */
+    0x12,0x4B,0x04,0x02,0x11,0x13,0x0A,0x10,  /* 000003B8    ".K......" */
+    0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,  /* 000003C0    ".....n.M" */
+    0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,  /* 000003C8    ".....J.." */
+    0x12,0x33,0x05,0x12,0x0A,0x02,0x0D,0x74,  /* 000003D0    ".3.....t" */
+    0x31,0x2F,0x74,0x33,0x00,0x01,0x12,0x07,  /* 000003D8    "1/t3...." */
+    0x02,0x0D,0x74,0x38,0x00,0x00,0x12,0x07,  /* 000003E0    "..t8...." */
+    0x02,0x0D,0x74,0x39,0x00,0x00,0x12,0x08,  /* 000003E8    "..t9...." */
+    0x02,0x0D,0x74,0x31,0x30,0x00,0x00,0x12,  /* 000003F0    "..t10..." */
+    0x0C,0x02,0x0D,0x74,0x31,0x31,0x2F,0x74,  /* 000003F8    "...t11/t" */
+    0x31,0x32,0x00,0x00,0x5B,0x82,0x4B,0x07,  /* 00000400    "12..[.K." */
+    0x42,0x4B,0x4C,0x54,0x08,0x5F,0x48,0x49,  /* 00000408    "BKLT._HI" */
+    0x44,0x0D,0x50,0x52,0x50,0x30,0x30,0x30,  /* 00000410    "D.PRP000" */
+    0x30,0x00,0x08,0x5F,0x44,0x53,0x44,0x12,  /* 00000418    "0.._DSD." */
+    0x41,0x06,0x02,0x11,0x13,0x0A,0x10,0x14,  /* 00000420    "A......." */
+    0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,  /* 00000428    "....n.M." */
+    0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,  /* 00000430    "....J..." */
+    0x49,0x04,0x04,0x12,0x0C,0x02,0x0D,0x70,  /* 00000438    "I......p" */
+    0x72,0x65,0x73,0x65,0x6E,0x74,0x00,0x01,  /* 00000440    "resent.." */
+    0x12,0x10,0x02,0x0D,0x70,0x77,0x6D,0x20,  /* 00000448    "....pwm " */
+    0x66,0x72,0x65,0x71,0x20,0x68,0x7A,0x00,  /* 00000450    "freq hz." */
+    0x00,0x12,0x13,0x02,0x0D,0x61,0x63,0x74,  /* 00000458    ".....act" */
+    0x69,0x76,0x65,0x20,0x6C,0x6F,0x77,0x20,  /* 00000460    "ive low " */
+    0x70,0x77,0x6D,0x00,0x00,0x12,0x13,0x02,  /* 00000468    "pwm....." */
+    0x0D,0x6D,0x69,0x6E,0x20,0x62,0x72,0x69,  /* 00000470    ".min bri" */
+    0x67,0x68,0x74,0x6E,0x65,0x73,0x73,0x00,  /* 00000478    "ghtness." */
+    0x00,0x5B,0x82,0x4E,0x0A,0x50,0x53,0x52,  /* 00000480    ".[.N.PSR" */
+    0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,  /* 00000488    "_._HID.P" */
+    0x52,0x50,0x30,0x30,0x30,0x30,0x00,0x08,  /* 00000490    "RP0000.." */
+    0x5F,0x44,0x53,0x44,0x12,0x44,0x09,0x02,  /* 00000498    "_DSD.D.." */
+    0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,  /* 000004A0    "........" */
+    0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,  /* 000004A8    ".n.M...." */
+    0xBF,0x4A,0xA3,0x01,0x12,0x4C,0x07,0x06,  /* 000004B0    ".J...L.." */
+    0x12,0x0E,0x02,0x0D,0x66,0x75,0x6C,0x6C,  /* 000004B8    "....full" */
+    0x20,0x6C,0x69,0x6E,0x6B,0x00,0x00,0x12,  /* 000004C0    " link..." */
+    0x17,0x02,0x0D,0x72,0x65,0x71,0x75,0x69,  /* 000004C8    "...requi" */
+    0x72,0x65,0x20,0x61,0x75,0x78,0x20,0x77,  /* 000004D0    "re aux w" */
+    0x61,0x6B,0x65,0x75,0x70,0x00,0x00,0x12,  /* 000004D8    "akeup..." */
+    0x10,0x02,0x0D,0x69,0x64,0x6C,0x65,0x20,  /* 000004E0    "...idle " */
+    0x66,0x72,0x61,0x6D,0x65,0x73,0x00,0x00,  /* 000004E8    "frames.." */
+    0x12,0x12,0x02,0x0D,0x6C,0x69,0x6E,0x65,  /* 000004F0    "....line" */
+    0x73,0x20,0x74,0x6F,0x20,0x77,0x61,0x69,  /* 000004F8    "s to wai" */
+    0x74,0x00,0x00,0x12,0x14,0x02,0x0D,0x74,  /* 00000500    "t......t" */
+    0x70,0x31,0x20,0x77,0x61,0x6B,0x65,0x75,  /* 00000508    "p1 wakeu" */
+    0x70,0x20,0x74,0x69,0x6D,0x65,0x00,0x00,  /* 00000510    "p time.." */
+    0x12,0x18,0x02,0x0D,0x74,0x70,0x32,0x20,  /* 00000518    "....tp2 " */
+    0x74,0x70,0x33,0x20,0x77,0x61,0x6B,0x65,  /* 00000520    "tp3 wake" */
+    0x75,0x70,0x20,0x74,0x69,0x6D,0x65,0x00,  /* 00000528    "up time." */
+    0x00,0x5B,0x82,0x45,0x0B,0x44,0x53,0x49,  /* 00000530    ".[.E.DSI" */
+    0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,  /* 00000538    "_._HID.P" */
+    0x52,0x50,0x30,0x30,0x30,0x30,0x00,0x08,  /* 00000540    "RP0000.." */
+    0x5F,0x44,0x53,0x44,0x12,0x4B,0x09,0x02,  /* 00000548    "_DSD.K.." */
+    0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,  /* 00000550    "........" */
+    0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,  /* 00000558    ".n.M...." */
+    0xBF,0x4A,0xA3,0x01,0x12,0x43,0x08,0x08,  /* 00000560    ".J...C.." */
+    0x12,0x0D,0x02,0x0D,0x68,0x61,0x73,0x20,  /* 00000568    "....has " */
+    0x6D,0x69,0x70,0x69,0x00,0x00,0x12,0x11,  /* 00000570    "mipi...." */
+    0x02,0x0D,0x64,0x73,0x69,0x20,0x70,0x61,  /* 00000578    "..dsi pa" */
+    0x6E,0x65,0x6C,0x20,0x69,0x64,0x00,0x00,  /* 00000580    "nel id.." */
+    0x12,0x0F,0x02,0x0D,0x64,0x73,0x69,0x20,  /* 00000588    "....dsi " */
+    0x63,0x6F,0x6E,0x66,0x69,0x67,0x00,0x00,  /* 00000590    "config.." */
+    0x12,0x0C,0x02,0x0D,0x64,0x73,0x69,0x20,  /* 00000598    "....dsi " */
+    0x70,0x70,0x73,0x00,0x00,0x12,0x14,0x02,  /* 000005A0    "pps....." */
+    0x0D,0x64,0x73,0x69,0x20,0x73,0x65,0x71,  /* 000005A8    ".dsi seq" */
+    0x20,0x76,0x65,0x72,0x73,0x69,0x6F,0x6E,  /* 000005B0    " version" */
+    0x00,0x00,0x12,0x0D,0x02,0x0D,0x64,0x73,  /* 000005B8    "......ds" */
+    0x69,0x20,0x64,0x61,0x74,0x61,0x00,0x00,  /* 000005C0    "i data.." */
+    0x12,0x0D,0x02,0x0D,0x64,0x73,0x69,0x20,  /* 000005C8    "....dsi " */
+    0x73,0x69,0x7A,0x65,0x00,0x00,0x12,0x11,  /* 000005D0    "size...." */
+    0x02,0x0D,0x64,0x73,0x69,0x20,0x73,0x65,  /* 000005D8    "..dsi se" */
+    0x71,0x75,0x65,0x6E,0x63,0x65,0x00,0x00,  /* 000005E0    "quence.." */
+    0x5B,0x82,0x4F,0x23,0x57,0x52,0x4B,0x53,  /* 000005E8    "[.O#WRKS" */
+    0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,0x52,  /* 000005F0    "._HID.PR" */
+    0x50,0x30,0x30,0x30,0x30,0x00,0x08,0x5F,  /* 000005F8    "P0000.._" */
+    0x44,0x53,0x44,0x12,0x45,0x22,0x02,0x11,  /* 00000600    "DSD.E".." */
+    0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,0xBA,  /* 00000608    "........" */
+    0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,0xBF,  /* 00000610    "n.M....." */
+    0x4A,0xA3,0x01,0x12,0x4D,0x20,0x0C,0x12,  /* 00000618    "J...M .." */
+    0x2E,0x02,0x0D,0x57,0x61,0x44,0x69,0x73,  /* 00000620    "...WaDis" */
+    0x61,0x62,0x6C,0x65,0x50,0x61,0x72,0x74,  /* 00000628    "ablePart" */
+    0x69,0x61,0x6C,0x49,0x6E,0x73,0x74,0x53,  /* 00000630    "ialInstS" */
+    0x68,0x6F,0x6F,0x74,0x64,0x6F,0x77,0x6E,  /* 00000638    "hootdown" */
+    0x00,0x12,0x0C,0x04,0x0B,0xF0,0xE4,0x0B,  /* 00000640    "........" */
+    0x00,0x01,0x0B,0x00,0x01,0x01,0x12,0x31,  /* 00000648    ".......1" */
+    0x02,0x0D,0x57,0x61,0x44,0x69,0x73,0x61,  /* 00000650    "..WaDisa" */
+    0x62,0x6C,0x65,0x54,0x68,0x72,0x65,0x61,  /* 00000658    "bleThrea" */
+    0x64,0x53,0x74,0x61,0x6C,0x6C,0x44,0x6F,  /* 00000660    "dStallDo" */
+    0x70,0x43,0x6C,0x6F,0x63,0x6B,0x47,0x61,  /* 00000668    "pClockGa" */
+    0x74,0x69,0x6E,0x67,0x00,0x12,0x0A,0x04,  /* 00000670    "ting...." */
+    0x0B,0xF0,0xE4,0x0A,0x20,0x0A,0x20,0x01,  /* 00000678    ".... . ." */
+    0x12,0x24,0x02,0x0D,0x57,0x61,0x44,0x69,  /* 00000680    ".$..WaDi" */
+    0x73,0x61,0x62,0x6C,0x65,0x44,0x6F,0x70,  /* 00000688    "sableDop" */
+    0x43,0x6C,0x6F,0x63,0x6B,0x47,0x61,0x74,  /* 00000690    "ClockGat" */
+    0x69,0x6E,0x67,0x00,0x12,0x08,0x04,0x0B,  /* 00000698    "ing....." */
+    0xF4,0xE4,0x01,0x01,0x01,0x12,0x2A,0x02,  /* 000006A0    "......*." */
+    0x0D,0x57,0x61,0x44,0x69,0x73,0x61,0x62,  /* 000006A8    ".WaDisab" */
+    0x6C,0x65,0x53,0x61,0x6D,0x70,0x6C,0x65,  /* 000006B0    "leSample" */
+    0x72,0x50,0x6F,0x77,0x65,0x72,0x42,0x79,  /* 000006B8    "rPowerBy" */
+    0x70,0x61,0x73,0x73,0x00,0x12,0x0A,0x04,  /* 000006C0    "pass...." */
+    0x0B,0x84,0xE1,0x0A,0x02,0x0A,0x02,0x01,  /* 000006C8    "........" */
+    0x12,0x2E,0x02,0x0D,0x57,0x61,0x44,0x69,  /* 000006D0    "....WaDi" */
+    0x73,0x61,0x62,0x6C,0x65,0x50,0x61,0x72,  /* 000006D8    "sablePar" */
+    0x74,0x69,0x61,0x6C,0x49,0x6E,0x73,0x74,  /* 000006E0    "tialInst" */
+    0x53,0x68,0x6F,0x6F,0x74,0x64,0x6F,0x77,  /* 000006E8    "Shootdow" */
+    0x6E,0x00,0x12,0x0C,0x04,0x0B,0xF0,0xE4,  /* 000006F0    "n......." */
+    0x0B,0x00,0x01,0x0B,0x00,0x01,0x01,0x12,  /* 000006F8    "........" */
+    0x31,0x02,0x0D,0x57,0x61,0x44,0x69,0x73,  /* 00000700    "1..WaDis" */
+    0x61,0x62,0x6C,0x65,0x54,0x68,0x72,0x65,  /* 00000708    "ableThre" */
+    0x61,0x64,0x53,0x74,0x61,0x6C,0x6C,0x44,  /* 00000710    "adStallD" */
+    0x6F,0x70,0x43,0x6C,0x6F,0x63,0x6B,0x47,  /* 00000718    "opClockG" */
+    0x61,0x74,0x69,0x6E,0x67,0x00,0x12,0x0A,  /* 00000720    "ating..." */
+    0x04,0x0B,0xF0,0xE4,0x0A,0x20,0x0A,0x20,  /* 00000728    "..... . " */
+    0x01,0x12,0x24,0x02,0x0D,0x57,0x61,0x44,  /* 00000730    "..$..WaD" */
+    0x69,0x73,0x61,0x62,0x6C,0x65,0x44,0x6F,  /* 00000738    "isableDo" */
+    0x70,0x43,0x6C,0x6F,0x63,0x6B,0x47,0x61,  /* 00000740    "pClockGa" */
+    0x74,0x69,0x6E,0x67,0x00,0x12,0x08,0x04,  /* 00000748    "ting...." */
+    0x0B,0xF4,0xE4,0x01,0x01,0x01,0x12,0x26,  /* 00000750    ".......&" */
+    0x02,0x0D,0x57,0x61,0x44,0x69,0x73,0x61,  /* 00000758    "..WaDisa" */
+    0x62,0x6C,0x65,0x44,0x6F,0x70,0x43,0x6C,  /* 00000760    "bleDopCl" */
+    0x6F,0x63,0x6B,0x47,0x61,0x74,0x69,0x6E,  /* 00000768    "ockGatin" */
+    0x67,0x00,0x12,0x0A,0x04,0x0B,0x84,0xE1,  /* 00000770    "g......." */
+    0x0A,0x02,0x0A,0x02,0x01,0x12,0x2D,0x02,  /* 00000778    "......-." */
+    0x0D,0x57,0x61,0x44,0x69,0x73,0x61,0x62,  /* 00000780    ".WaDisab" */
+    0x6C,0x65,0x46,0x65,0x6E,0x63,0x65,0x44,  /* 00000788    "leFenceD" */
+    0x65,0x73,0x74,0x69,0x6E,0x61,0x74,0x69,  /* 00000790    "estinati" */
+    0x6F,0x6E,0x54,0x6F,0x53,0x4C,0x4D,0x00,  /* 00000798    "onToSLM." */
+    0x12,0x0A,0x04,0x0B,0x00,0x73,0x0A,0x10,  /* 000007A0    ".....s.." */
+    0x0A,0x10,0x01,0x12,0x33,0x02,0x0D,0x57,  /* 000007A8    "....3..W" */
+    0x61,0x44,0x69,0x73,0x61,0x62,0x6C,0x65,  /* 000007B0    "aDisable" */
+    0x46,0x65,0x6E,0x63,0x65,0x44,0x65,0x73,  /* 000007B8    "FenceDes" */
+    0x74,0x69,0x6E,0x61,0x74,0x69,0x6F,0x6E,  /* 000007C0    "tination" */
+    0x54,0x6F,0x53,0x4C,0x4D,0x20,0x47,0x54,  /* 000007C8    "ToSLM GT" */
+    0x33,0x00,0x12,0x0C,0x04,0x0B,0x00,0x73,  /* 000007D0    "3......s" */
+    0x0B,0x00,0x40,0x0B,0x00,0x40,0x01,0x12,  /* 000007D8    "..@..@.." */
+    0x2A,0x02,0x0D,0x57,0x61,0x34,0x78,0x34,  /* 000007E0    "*..Wa4x4" */
+    0x53,0x54,0x43,0x4F,0x70,0x74,0x69,0x6D,  /* 000007E8    "STCOptim" */
+    0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,0x44,  /* 000007F0    "izationD" */
+    0x69,0x73,0x61,0x62,0x6C,0x65,0x00,0x12,  /* 000007F8    "isable.." */
+    0x0A,0x04,0x0B,0x04,0x70,0x0A,0x40,0x0A,  /* 00000800    "....p.@." */
+    0x40,0x01,0x12,0x1E,0x02,0x0D,0x57,0x61,  /* 00000808    "@.....Wa" */
+    0x31,0x36,0x78,0x34,0x68,0x61,0x73,0x68,  /* 00000810    "16x4hash" */
+    0x69,0x6E,0x67,0x00,0x12,0x0C,0x04,0x0B,  /* 00000818    "ing....." */
+    0x08,0x70,0x0B,0x00,0x02,0x0B,0x80,0x02,  /* 00000820    ".p......" */
+    0x01,0x5B,0x82,0x42,0x1A,0x43,0x52,0x54,  /* 00000828    ".[.B.CRT" */
+    0x43,0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,  /* 00000830    "C._HID.P" */
+    0x52,0x50,0x30,0x30,0x30,0x30,0x00,0x08,  /* 00000838    "RP0000.." */
+    0x5F,0x44,0x53,0x44,0x12,0x34,0x02,0x11,  /* 00000840    "_DSD.4.." */
+    0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,0xBA,  /* 00000848    "........" */
+    0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,0xBF,  /* 00000850    "n.M....." */
+    0x4A,0xA3,0x01,0x12,0x1D,0x02,0x12,0x0E,  /* 00000858    "J......." */
+    0x02,0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,  /* 00000860    "..enable" */
+    0x64,0x00,0x0D,0x33,0x00,0x12,0x0B,0x02,  /* 00000868    "d..3...." */
+    0x0D,0x63,0x6F,0x75,0x6E,0x74,0x00,0x0A,  /* 00000870    ".count.." */
+    0x03,0x5B,0x82,0x4F,0x06,0x49,0x44,0x30,  /* 00000878    ".[.O.ID0" */
+    0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,  /* 00000880    "_._HID.P" */
+    0x52,0x50,0x30,0x30,0x30,0x30,0x00,0x08,  /* 00000888    "RP0000.." */
+    0x5F,0x44,0x53,0x44,0x12,0x45,0x05,0x02,  /* 00000890    "_DSD.E.." */
+    0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,  /* 00000898    "........" */
+    0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,  /* 000008A0    ".n.M...." */
+    0xBF,0x4A,0xA3,0x01,0x12,0x3D,0x04,0x12,  /* 000008A8    ".J...=.." */
+    0x07,0x02,0x0D,0x69,0x64,0x00,0x00,0x12,  /* 000008B0    "...id..." */
+    0x16,0x02,0x0D,0x63,0x61,0x6E,0x76,0x61,  /* 000008B8    "...canva" */
+    0x73,0x5F,0x63,0x6F,0x6C,0x6F,0x72,0x00,  /* 000008C0    "s_color." */
+    0x12,0x05,0x03,0x00,0x00,0x00,0x12,0x0E,  /* 000008C8    "........" */
+    0x02,0x0D,0x62,0x6C,0x65,0x6E,0x64,0x5F,  /* 000008D0    "..blend_" */
+    0x65,0x71,0x75,0x00,0x00,0x12,0x0C,0x02,  /* 000008D8    "equ....." */
+    0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,0x64,  /* 000008E0    ".enabled" */
+    0x00,0x01,0x5B,0x82,0x4F,0x06,0x49,0x44,  /* 000008E8    "..[.O.ID" */
+    0x31,0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,  /* 000008F0    "1_._HID." */
+    0x50,0x52,0x50,0x30,0x30,0x30,0x30,0x00,  /* 000008F8    "PRP0000." */
+    0x08,0x5F,0x44,0x53,0x44,0x12,0x45,0x05,  /* 00000900    "._DSD.E." */
+    0x02,0x11,0x13,0x0A,0x10,0x14,0xD8,0xFF,  /* 00000908    "........" */
+    0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,0x91,0xBC,  /* 00000910    "..n.M..." */
+    0x9B,0xBF,0x4A,0xA3,0x01,0x12,0x3D,0x04,  /* 00000918    "..J...=." */
+    0x12,0x07,0x02,0x0D,0x69,0x64,0x00,0x01,  /* 00000920    "....id.." */
+    0x12,0x16,0x02,0x0D,0x63,0x61,0x6E,0x76,  /* 00000928    "....canv" */
+    0x61,0x73,0x5F,0x63,0x6F,0x6C,0x6F,0x72,  /* 00000930    "as_color" */
+    0x00,0x12,0x05,0x03,0x00,0x00,0x00,0x12,  /* 00000938    "........" */
+    0x0E,0x02,0x0D,0x62,0x6C,0x65,0x6E,0x64,  /* 00000940    "...blend" */
+    0x5F,0x65,0x71,0x75,0x00,0x00,0x12,0x0C,  /* 00000948    "_equ...." */
+    0x02,0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,  /* 00000950    "..enable" */
+    0x64,0x00,0x01,0x5B,0x82,0x40,0x07,0x49,  /* 00000958    "d..[.@.I" */
+    0x44,0x32,0x5F,0x08,0x5F,0x48,0x49,0x44,  /* 00000960    "D2_._HID" */
+    0x0D,0x50,0x52,0x50,0x30,0x30,0x30,0x30,  /* 00000968    ".PRP0000" */
+    0x00,0x08,0x5F,0x44,0x53,0x44,0x12,0x46,  /* 00000970    ".._DSD.F" */
+    0x05,0x02,0x11,0x13,0x0A,0x10,0x14,0xD8,  /* 00000978    "........" */
+    0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,0x91,  /* 00000980    "...n.M.." */
+    0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,0x3E,  /* 00000988    "...J...>" */
+    0x04,0x12,0x08,0x02,0x0D,0x69,0x64,0x00,  /* 00000990    ".....id." */
+    0x0A,0x02,0x12,0x16,0x02,0x0D,0x63,0x61,  /* 00000998    "......ca" */
+    0x6E,0x76,0x61,0x73,0x5F,0x63,0x6F,0x6C,  /* 000009A0    "nvas_col" */
+    0x6F,0x72,0x00,0x12,0x05,0x03,0x00,0x00,  /* 000009A8    "or......" */
+    0x00,0x12,0x0E,0x02,0x0D,0x62,0x6C,0x65,  /* 000009B0    ".....ble" */
+    0x6E,0x64,0x5F,0x65,0x71,0x75,0x00,0x00,  /* 000009B8    "nd_equ.." */
+    0x12,0x0C,0x02,0x0D,0x65,0x6E,0x61,0x62,  /* 000009C0    "....enab" */
+    0x6C,0x65,0x64,0x00,0x01,0x5B,0x82,0x45,  /* 000009C8    "led..[.E" */
+    0x0E,0x50,0x4C,0x4E,0x53,0x08,0x5F,0x48,  /* 000009D0    ".PLNS._H" */
+    0x49,0x44,0x0D,0x50,0x52,0x50,0x30,0x30,  /* 000009D8    "ID.PRP00" */
+    0x30,0x30,0x00,0x08,0x5F,0x44,0x53,0x44,  /* 000009E0    "00.._DSD" */
+    0x12,0x25,0x02,0x11,0x13,0x0A,0x10,0x14,  /* 000009E8    ".%......" */
+    0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,  /* 000009F0    "....n.M." */
+    0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,  /* 000009F8    "....J..." */
+    0x0E,0x01,0x12,0x0B,0x02,0x0D,0x63,0x6F,  /* 00000A00    "......co" */
+    0x75,0x6E,0x74,0x00,0x0A,0x02,0x5B,0x82,  /* 00000A08    "unt...[." */
+    0x41,0x05,0x50,0x4C,0x30,0x5F,0x08,0x5F,  /* 00000A10    "A.PL0_._" */
+    0x48,0x49,0x44,0x0D,0x50,0x52,0x50,0x30,  /* 00000A18    "HID.PRP0" */
+    0x30,0x30,0x30,0x00,0x08,0x5F,0x44,0x53,  /* 00000A20    "000.._DS" */
+    0x44,0x12,0x37,0x02,0x11,0x13,0x0A,0x10,  /* 00000A28    "D.7....." */
+    0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,  /* 00000A30    ".....n.M" */
+    0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,  /* 00000A38    ".....J.." */
+    0x12,0x20,0x02,0x12,0x0A,0x02,0x0D,0x67,  /* 00000A40    ". .....g" */
+    0x61,0x6D,0x6D,0x61,0x00,0x01,0x12,0x12,  /* 00000A48    "amma...." */
+    0x02,0x0D,0x63,0x6F,0x6C,0x6F,0x72,0x2D,  /* 00000A50    "..color-" */
+    0x6B,0x65,0x79,0x00,0x0C,0xFF,0xFF,0xFF,  /* 00000A58    "key....." */
+    0xFF,0x5B,0x82,0x41,0x05,0x50,0x4C,0x31,  /* 00000A60    ".[.A.PL1" */
+    0x5F,0x08,0x5F,0x48,0x49,0x44,0x0D,0x50,  /* 00000A68    "_._HID.P" */
+    0x52,0x50,0x30,0x30,0x30,0x30,0x00,0x08,  /* 00000A70    "RP0000.." */
+    0x5F,0x44,0x53,0x44,0x12,0x37,0x02,0x11,  /* 00000A78    "_DSD.7.." */
+    0x13,0x0A,0x10,0x14,0xD8,0xFF,0xDA,0xBA,  /* 00000A80    "........" */
+    0x6E,0x8C,0x4D,0x8A,0x91,0xBC,0x9B,0xBF,  /* 00000A88    "n.M....." */
+    0x4A,0xA3,0x01,0x12,0x20,0x02,0x12,0x0A,  /* 00000A90    "J... ..." */
+    0x02,0x0D,0x67,0x61,0x6D,0x6D,0x61,0x00,  /* 00000A98    "..gamma." */
+    0x00,0x12,0x12,0x02,0x0D,0x63,0x6F,0x6C,  /* 00000AA0    ".....col" */
+    0x6F,0x72,0x2D,0x6B,0x65,0x79,0x00,0x0C,  /* 00000AA8    "or-key.." */
+    0xFF,0xFF,0xFF,0xFF,0x5B,0x82,0x44,0x19,  /* 00000AB0    "....[.D." */
+    0x43,0x4E,0x43,0x54,0x08,0x5F,0x48,0x49,  /* 00000AB8    "CNCT._HI" */
+    0x44,0x0D,0x50,0x52,0x50,0x30,0x30,0x30,  /* 00000AC0    "D.PRP000" */
+    0x30,0x00,0x08,0x5F,0x44,0x53,0x44,0x12,  /* 00000AC8    "0.._DSD." */
+    0x25,0x02,0x11,0x13,0x0A,0x10,0x14,0xD8,  /* 00000AD0    "%......." */
+    0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,0x91,  /* 00000AD8    "...n.M.." */
+    0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,0x0E,  /* 00000AE0    "...J...." */
+    0x01,0x12,0x0B,0x02,0x0D,0x63,0x6F,0x75,  /* 00000AE8    ".....cou" */
+    0x6E,0x74,0x00,0x0A,0x02,0x5B,0x82,0x4D,  /* 00000AF0    "nt...[.M" */
+    0x07,0x43,0x30,0x5F,0x5F,0x08,0x5F,0x48,  /* 00000AF8    ".C0__._H" */
+    0x49,0x44,0x0D,0x50,0x52,0x50,0x30,0x30,  /* 00000B00    "ID.PRP00" */
+    0x30,0x30,0x00,0x08,0x5F,0x44,0x53,0x44,  /* 00000B08    "00.._DSD" */
+    0x12,0x43,0x06,0x02,0x11,0x13,0x0A,0x10,  /* 00000B10    ".C......" */
+    0x14,0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,  /* 00000B18    ".....n.M" */
+    0x8A,0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,  /* 00000B20    ".....J.." */
+    0x12,0x4B,0x04,0x04,0x12,0x10,0x02,0x0D,  /* 00000B28    ".K......" */
+    0x6E,0x61,0x6D,0x65,0x00,0x0D,0x61,0x6E,  /* 00000B30    "name..an" */
+    0x61,0x6C,0x6F,0x67,0x00,0x12,0x0C,0x02,  /* 00000B38    "alog...." */
+    0x0D,0x65,0x6E,0x61,0x62,0x6C,0x65,0x64,  /* 00000B40    ".enabled" */
+    0x00,0x01,0x12,0x14,0x02,0x0D,0x62,0x69,  /* 00000B48    "......bi" */
+    0x74,0x73,0x5F,0x70,0x65,0x72,0x5F,0x63,  /* 00000B50    "ts_per_c" */
+    0x6F,0x6C,0x6F,0x72,0x00,0x0A,0x06,0x12,  /* 00000B58    "olor...." */
+    0x14,0x02,0x0D,0x63,0x6F,0x6E,0x73,0x74,  /* 00000B60    "...const" */
+    0x61,0x6E,0x74,0x5F,0x61,0x6C,0x70,0x68,  /* 00000B68    "ant_alph" */
+    0x61,0x00,0x0A,0xFF,0x5B,0x82,0x44,0x0D,  /* 00000B70    "a...[.D." */
+    0x43,0x31,0x5F,0x5F,0x08,0x5F,0x48,0x49,  /* 00000B78    "C1__._HI" */
+    0x44,0x0D,0x50,0x52,0x50,0x30,0x30,0x30,  /* 00000B80    "D.PRP000" */
+    0x30,0x00,0x08,0x5F,0x44,0x53,0x44,0x12,  /* 00000B88    "0.._DSD." */
+    0x4A,0x0B,0x02,0x11,0x13,0x0A,0x10,0x14,  /* 00000B90    "J......." */
+    0xD8,0xFF,0xDA,0xBA,0x6E,0x8C,0x4D,0x8A,  /* 00000B98    "....n.M." */
+    0x91,0xBC,0x9B,0xBF,0x4A,0xA3,0x01,0x12,  /* 00000BA0    "....J..." */
+    0x42,0x0A,0x07,0x12,0x17,0x02,0x0D,0x6E,  /* 00000BA8    "B......n" */
+    0x61,0x6D,0x65,0x00,0x0D,0x64,0x69,0x73,  /* 00000BB0    "ame..dis" */
+    0x70,0x6C,0x61,0x79,0x70,0x6F,0x72,0x74,  /* 00000BB8    "playport" */
+    0x5F,0x61,0x00,0x12,0x0C,0x02,0x0D,0x65,  /* 00000BC0    "_a.....e" */
+    0x6E,0x61,0x62,0x6C,0x65,0x64,0x00,0x01,  /* 00000BC8    "nabled.." */
+    0x12,0x1D,0x02,0x0D,0x73,0x63,0x61,0x6C,  /* 00000BD0    "....scal" */
+    0x69,0x6E,0x67,0x5F,0x6D,0x6F,0x64,0x65,  /* 00000BD8    "ing_mode" */
+    0x00,0x0D,0x46,0x75,0x6C,0x6C,0x20,0x61,  /* 00000BE0    "..Full a" */
+    0x73,0x70,0x65,0x63,0x74,0x00,0x12,0x14,  /* 00000BE8    "spect..." */
+    0x02,0x0D,0x61,0x75,0x64,0x69,0x6F,0x00,  /* 00000BF0    "..audio." */
+    0x0D,0x66,0x6F,0x72,0x63,0x65,0x2D,0x64,  /* 00000BF8    ".force-d" */
+    0x76,0x69,0x00,0x12,0x1C,0x02,0x0D,0x42,  /* 00000C00    "vi.....B" */
+    0x72,0x6F,0x61,0x64,0x63,0x61,0x73,0x74,  /* 00000C08    "roadcast" */
+    0x5F,0x52,0x47,0x42,0x00,0x0D,0x41,0x75,  /* 00000C10    "_RGB..Au" */
+    0x74,0x6F,0x6D,0x61,0x74,0x69,0x63,0x00,  /* 00000C18    "tomatic." */
+    0x12,0x14,0x02,0x0D,0x62,0x69,0x74,0x73,  /* 00000C20    "....bits" */
+    0x5F,0x70,0x65,0x72,0x5F,0x63,0x6F,0x6C,  /* 00000C28    "_per_col" */
+    0x6F,0x72,0x00,0x0A,0x08,0x12,0x14,0x02,  /* 00000C30    "or......" */
+    0x0D,0x63,0x6F,0x6E,0x73,0x74,0x61,0x6E,  /* 00000C38    ".constan" */
+    0x74,0x5F,0x61,0x6C,0x70,0x68,0x61,0x00,  /* 00000C40    "t_alpha." */
+    0x0A,0xFF                                 /* 00000C48    ".."       */
 };
-- 
2.1.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [RFC 00/12] i915 init-time configuration.
  2015-02-12 23:41 [RFC 00/12] i915 init-time configuration Bob Paauwe
                   ` (11 preceding siblings ...)
  2015-02-12 23:41 ` [RFC 12/12] drm/i915/config: Add ACPI device examples for VBT configuration Bob Paauwe
@ 2015-02-13  8:08 ` Jani Nikula
  2015-02-13 17:17   ` Bob Paauwe
  12 siblings, 1 reply; 32+ messages in thread
From: Jani Nikula @ 2015-02-13  8:08 UTC (permalink / raw)
  To: Bob Paauwe, intel-gfx

On Fri, 13 Feb 2015, Bob Paauwe <bob.j.paauwe@intel.com> wrote:
> Background:
>
> This capability is targeted at deeply embedded appliance like devices
> that make use of Intel integrated graphics.  There are a few use cases
> that are not currently supported by the i915 driver.  For example,
> they may not be running userspace code that is capable of querying and
> setting the various DRM properties and would like them set during the
> driver initialization. Also they may be using a custom firmware bootloader
> that does not include any graphics initialization or VBT information.  
>
> This level of initialization configuration has been available in
> the Intel EMGD kernel driver and a similar level of configurability will
> be expected as designs transition to the i915 driver.
>
> This patch set provides a framework that makes use of ACPI property
> tables containing configuration information.  It also includes some
> examples on how this may be applied to various aspects of the i915
> driver initialization.

The biggest issue I have with this series is the introduction of another
source of configuration in addition to VBT (and to a lesser extent ACPI
OpRegion) without an attempt to abstract them. Information from both
will get used. The mixture is completed in patch 9 that initializes some
of the same data structures as intel_bios.c but without reuse of the
code.

Maybe we need to better abstract our use of the VBT information to begin
with, so that we could plug in additional (complementary or replacement)
sources of the configuration. Offhand, I am not sure if what you propose
as intel_config.c API could be developed into such an abstraction, or if
there's something ready made in kernel we could use.

I do know we already and historically have had problems with the forward
compatibility of the VBT data. It's been getting better, but we need to
avoid the same mistakes. On a related note, I'd really appreciate it if
the specification for your data could be made public.

Oh, one other thing, this thing needs to build with CONFIG_ACPI=n. At
least that's been the case for i915 for a long time.

I'll add some random notes on the patches too.

BR,
Jani.


>
> Series description:
>
> Patch 1 creates the initial framework. It looks up a specific ACPI
> property table and builds lists containing the configuration found
> in that table.  It includes functions that can make use of that 
> configuration information.
>
> Patch 2 adds a function to i915 that provides a unique name for
> each output.  We previously had something similar to this in the
> driver for debug output, it was not be used and removed recently.
>
> Patch 3 is the first example usage.  We check the configuration for
> a CRTC bits-per-pixel value and use that if EDID does not provide
> this.
>
> Patch 4 is an example of using the configuration to specify a 
> default value for the DP panel fitter property.
>
> Patch 5 is an example of using the configuration to specify default
> values for a couple of common connector properties.
>
> Patch 6 modifies the framework slightly to better support the 
> remaining examples.
>
> Patch 7 adds a function to the framework that looks for a 
> workaround section. If found, it builds a list of workarounds that
> can be used in place of of the workarounds hardcoded in the driver.
>
> Patch 8 changes the workaround initialization code to make use
> of the workaround list from the configuration instead of the
> built-in workaround list.
>
> Patch 9 adds functions to the frame work that look for a VBT
> section and parse that information into the driver's VBT structures.
>
> Patch 10 adds an example/test ACPI property table and adds code to
> the frame to build this table into the driver.  This is mainly for
> testing the framework, but may also be useful for truly embedded
> devices as a way to embed the configuration.
>
> Patch 11 adds an example workaround section to the test ACPI property
> table.
>
> Patch 12 add an example VBT section to the test ACPI property table.
>
> Bob Paauwe (12):
>   drm/i915/config: Initial framework
>   drm/i915/config: Introduce intel_output_name
>   drm/i915/config: Add init-time configuration of bits per color.
>   drm/i915/config: Set dp panel fitter property based on init-time
>     config.
>   drm/i915/config: Set general connector properties using config.
>   drm/i915/config: Split out allocation of list nodes.
>   drm/i915/config: Get workaround information from configuration.
>   drm/i915/config: Use workarounds list from configuration.
>   drm/i915/config: Add VBT settings configuration.
>   drm/i915/config: Introduce a test table and code to make use of it.
>   drm/i915/config: Add workaround properties to ACPI table.
>   drm/i915/config: Add ACPI device examples for VBT configuration.
>
>  drivers/gpu/drm/i915/Makefile            |    3 +-
>  drivers/gpu/drm/i915/i915-properties.asl |  340 ++++++++++
>  drivers/gpu/drm/i915/i915-properties.hex |  409 ++++++++++++
>  drivers/gpu/drm/i915/i915_dma.c          |    6 +
>  drivers/gpu/drm/i915/i915_drv.h          |   18 +
>  drivers/gpu/drm/i915/i915_params.c       |    6 +
>  drivers/gpu/drm/i915/intel_config.c      | 1002 ++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_display.c     |   71 +++
>  drivers/gpu/drm/i915/intel_dp.c          |    8 +-
>  drivers/gpu/drm/i915/intel_drv.h         |   33 +
>  drivers/gpu/drm/i915/intel_modes.c       |    8 +-
>  drivers/gpu/drm/i915/intel_ringbuffer.c  |   19 +-
>  12 files changed, 1909 insertions(+), 14 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/i915-properties.asl
>  create mode 100644 drivers/gpu/drm/i915/i915-properties.hex
>  create mode 100644 drivers/gpu/drm/i915/intel_config.c
>
> -- 
> 2.1.0
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 02/12] drm/i915/config: Introduce intel_output_name
  2015-02-12 23:41 ` [RFC 02/12] drm/i915/config: Introduce intel_output_name Bob Paauwe
@ 2015-02-13  8:12   ` Jani Nikula
  0 siblings, 0 replies; 32+ messages in thread
From: Jani Nikula @ 2015-02-13  8:12 UTC (permalink / raw)
  To: Bob Paauwe, intel-gfx

On Fri, 13 Feb 2015, Bob Paauwe <bob.j.paauwe@intel.com> wrote:
> Human readable name for each output type to correspond with names
> used in the ACPI property tables.

Could you not use drm_connector and drm_encoder type and name fields?

BR,
Jani.

>
> Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 57 ++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     |  1 +
>  2 files changed, 58 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 3b0fe9f..de6de83 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -12440,6 +12440,63 @@ static bool intel_crt_present(struct drm_device *dev)
>  	return true;
>  }
>  
> +/*
> + * Provide a name for the various outputs.
> + */
> +const char *intel_output_name(struct intel_connector *connector)
> +{
> +	int output;
> +	static const char *names[] = {
> +		[INTEL_OUTPUT_UNUSED] = "Unused",
> +		[INTEL_OUTPUT_ANALOG] = "Analog",
> +		[INTEL_OUTPUT_DVO] = "DVO",
> +		[INTEL_OUTPUT_SDVO] = "SDVO",
> +		[INTEL_OUTPUT_LVDS] = "LVDS",
> +		[INTEL_OUTPUT_TVOUT] = "TV",
> +		[INTEL_OUTPUT_HDMI] = "HDMI",
> +		[INTEL_OUTPUT_DISPLAYPORT] = "DisplayPort",
> +		[INTEL_OUTPUT_EDP] = "eDP",
> +		[INTEL_OUTPUT_DSI] = "DSI",
> +		[INTEL_OUTPUT_UNKNOWN] = "Unknown",
> +	};
> +	static const char *name_ex[] = {
> +		[0] = "HDMI_A",
> +		[1] = "HDMI_B",
> +		[2] = "HDMI_C",
> +		[3] = "HDMI_D",
> +		[4] = "DisplayPort_A",
> +		[5] = "DisplayPort_B",
> +		[6] = "DisplayPort_C",
> +		[7] = "DisplayPort_D",
> +		[8] = "eDP_A",
> +		[9] = "eDP_B",
> +		[10] = "eDP_C",
> +		[11] = "eDP_D",
> +	};
> +
> +	if (!connector || !connector->encoder)
> +		return "Unknown";
> +
> +	switch (connector->encoder->type) {
> +	case INTEL_OUTPUT_HDMI:
> +	case INTEL_OUTPUT_DISPLAYPORT:
> +	case INTEL_OUTPUT_EDP:
> +		output = ((connector->encoder->type - INTEL_OUTPUT_HDMI) * 4) +
> +			enc_to_dig_port(&connector->encoder->base)->port;
> +
> +		if (output < 0 || output >= ARRAY_SIZE(name_ex))
> +			return "Invalid";
> +
> +		return name_ex[output];
> +	default:
> +		if (output < 0 || output >= ARRAY_SIZE(names) || !names[output])
> +			return "Invalid";
> +
> +		return names[output];
> +	}
> +}
> +
> +
>  static void intel_setup_outputs(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index aefd95e..4c81ee9 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -893,6 +893,7 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
>  
>  /* intel_display.c */
>  extern const struct drm_plane_funcs intel_plane_funcs;
> +const char *intel_output_name(struct intel_connector *intel_connector);
>  bool intel_has_pending_fb_unpin(struct drm_device *dev);
>  int intel_pch_rawclk(struct drm_device *dev);
>  void intel_mark_busy(struct drm_device *dev);
> -- 
> 2.1.0
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 06/12] drm/i915/config: Split out allocation of list nodes.
  2015-02-12 23:41 ` [RFC 06/12] drm/i915/config: Split out allocation of list nodes Bob Paauwe
@ 2015-02-13  8:15   ` Jani Nikula
  0 siblings, 0 replies; 32+ messages in thread
From: Jani Nikula @ 2015-02-13  8:15 UTC (permalink / raw)
  To: Bob Paauwe, intel-gfx

On Fri, 13 Feb 2015, Bob Paauwe <bob.j.paauwe@intel.com> wrote:
> We'll reduce some duplicate code if we move the list node allocation
> to its own function when we start processing future config items like
> workaround or vbt information.

Should probably just be part of patch 1.

BR,
Jani.

>
> Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_config.c | 49 ++++++++++++++++++++++---------------
>  1 file changed, 29 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_config.c b/drivers/gpu/drm/i915/intel_config.c
> index cf7da93..fb495ed 100644
> --- a/drivers/gpu/drm/i915/intel_config.c
> +++ b/drivers/gpu/drm/i915/intel_config.c
> @@ -161,6 +161,21 @@ static bool node_property(struct intel_config_node *n,
>  }
>  
>  
> +static bool alloc_new_node(struct acpi_device *cl, struct list_head *list)
> +{
> +	struct intel_config_node *new_node;
> +
> +	new_node = kzalloc(sizeof(*new_node), GFP_KERNEL);
> +	if (!new_node)
> +		return false;
> +
> +	new_node->adev = cl;
> +	INIT_LIST_HEAD(&new_node->node);
> +	list_add_tail(&new_node->node, list);
> +
> +	return true;
> +}
> +
>  /**
>   * intel_config_init -
>   *
> @@ -232,26 +247,20 @@ void intel_config_init(struct drm_device *dev)
>  
>  		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);
> +		if (strcmp(cname, i915_COMPONENT_CRTC) == 0) {
> +			list_for_each_entry(cl, &component->children, node) {
> +				if (!alloc_new_node(cl, &info->crtc_list))
> +					goto bail;
> +			}
> +		} else if (strcmp(cname, i915_COMPONENT_CONNECTOR) == 0) {
> +			list_for_each_entry(cl, &component->children, node) {
> +				if (!alloc_new_node(cl, &info->crtc_list))
> +					goto bail;
> +			}
> +		} else if (strcmp(cname, i915_COMPONENT_PLANE) == 0) {
> +			list_for_each_entry(cl, &component->children, node) {
> +				if (!alloc_new_node(cl, &info->crtc_list))
> +					goto bail;
>  			}
>  		}
>  	}
> -- 
> 2.1.0
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 01/12] drm/i915/config: Initial framework
  2015-02-12 23:41 ` [RFC 01/12] drm/i915/config: Initial framework Bob Paauwe
@ 2015-02-13  8:19   ` Jani Nikula
  2015-02-24 16:17   ` Daniel Vetter
  1 sibling, 0 replies; 32+ messages in thread
From: Jani Nikula @ 2015-02-13  8:19 UTC (permalink / raw)
  To: Bob Paauwe, intel-gfx

On Fri, 13 Feb 2015, Bob Paauwe <bob.j.paauwe@intel.com> 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@intel.com>
> ---
>  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. ");

This isn't used now.

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

You should probably abstract this part to reduce duplication with
intel_config_shutdown. You also leak dev_priv->config_info there.

> +}
> +
> +
> +/**
> + * 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@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 00/12] i915 init-time configuration.
  2015-02-13  8:08 ` [RFC 00/12] i915 init-time configuration Jani Nikula
@ 2015-02-13 17:17   ` Bob Paauwe
  0 siblings, 0 replies; 32+ messages in thread
From: Bob Paauwe @ 2015-02-13 17:17 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Fri, 13 Feb 2015 10:08:52 +0200
Jani Nikula <jani.nikula@linux.intel.com> wrote:

Thanks Jani for the quick look and comments!

> On Fri, 13 Feb 2015, Bob Paauwe <bob.j.paauwe@intel.com> wrote:
> > Background:
> >
> > This capability is targeted at deeply embedded appliance like devices
> > that make use of Intel integrated graphics.  There are a few use cases
> > that are not currently supported by the i915 driver.  For example,
> > they may not be running userspace code that is capable of querying and
> > setting the various DRM properties and would like them set during the
> > driver initialization. Also they may be using a custom firmware bootloader
> > that does not include any graphics initialization or VBT information.  
> >
> > This level of initialization configuration has been available in
> > the Intel EMGD kernel driver and a similar level of configurability will
> > be expected as designs transition to the i915 driver.
> >
> > This patch set provides a framework that makes use of ACPI property
> > tables containing configuration information.  It also includes some
> > examples on how this may be applied to various aspects of the i915
> > driver initialization.
> 
> The biggest issue I have with this series is the introduction of another
> source of configuration in addition to VBT (and to a lesser extent ACPI
> OpRegion) without an attempt to abstract them. Information from both
> will get used. The mixture is completed in patch 9 that initializes some
> of the same data structures as intel_bios.c but without reuse of the
> code.

Yeah, I struggled with some of this too.  The general ID was that if
you have VBT, you'd most likely be using it and not this.  But if you
have firmware that doesn't have VBT, then there needs to be some way
to get this information into the driver. The EMGD driver has a
configuration structure and tool that that make it fairly easy to set
the configuration as it only supports a sub-set of what's in the VBT.
Here I tried to keep some of that by making the ACPI property table
also be fairly easy to create.  

The alternative would be to but binary blocks in the ACPI table that
correspond to the VBT blocks and send those blocks to the existing code
in the driver that parses them. 

> 
> Maybe we need to better abstract our use of the VBT information to begin
> with, so that we could plug in additional (complementary or replacement)
> sources of the configuration. Offhand, I am not sure if what you propose
> as intel_config.c API could be developed into such an abstraction, or if
> there's something ready made in kernel we could use.

I'll think about this some more and see if I can come up with some type
of abstraction.

> 
> I do know we already and historically have had problems with the forward
> compatibility of the VBT data. It's been getting better, but we need to
> avoid the same mistakes. On a related note, I'd really appreciate it if
> the specification for your data could be made public.

I don't see any reason why it couldn't be.  Right now it's just a
collection of ideas on areas that may be configurable at init-time and
thus somewhat ad-hoc.

> 
> Oh, one other thing, this thing needs to build with CONFIG_ACPI=n. At
> least that's been the case for i915 for a long time.

You're right, thanks for catching it. I'm pretty sure I had this at one
point, but lost it in all the iterations/re-basing.

> 
> I'll add some random notes on the patches too.
> 
> BR,
> Jani.
> 
> 
> >
> > Series description:
> >
> > Patch 1 creates the initial framework. It looks up a specific ACPI
> > property table and builds lists containing the configuration found
> > in that table.  It includes functions that can make use of that 
> > configuration information.
> >
> > Patch 2 adds a function to i915 that provides a unique name for
> > each output.  We previously had something similar to this in the
> > driver for debug output, it was not be used and removed recently.
> >
> > Patch 3 is the first example usage.  We check the configuration for
> > a CRTC bits-per-pixel value and use that if EDID does not provide
> > this.
> >
> > Patch 4 is an example of using the configuration to specify a 
> > default value for the DP panel fitter property.
> >
> > Patch 5 is an example of using the configuration to specify default
> > values for a couple of common connector properties.
> >
> > Patch 6 modifies the framework slightly to better support the 
> > remaining examples.
> >
> > Patch 7 adds a function to the framework that looks for a 
> > workaround section. If found, it builds a list of workarounds that
> > can be used in place of of the workarounds hardcoded in the driver.
> >
> > Patch 8 changes the workaround initialization code to make use
> > of the workaround list from the configuration instead of the
> > built-in workaround list.
> >
> > Patch 9 adds functions to the frame work that look for a VBT
> > section and parse that information into the driver's VBT structures.
> >
> > Patch 10 adds an example/test ACPI property table and adds code to
> > the frame to build this table into the driver.  This is mainly for
> > testing the framework, but may also be useful for truly embedded
> > devices as a way to embed the configuration.
> >
> > Patch 11 adds an example workaround section to the test ACPI property
> > table.
> >
> > Patch 12 add an example VBT section to the test ACPI property table.
> >
> > Bob Paauwe (12):
> >   drm/i915/config: Initial framework
> >   drm/i915/config: Introduce intel_output_name
> >   drm/i915/config: Add init-time configuration of bits per color.
> >   drm/i915/config: Set dp panel fitter property based on init-time
> >     config.
> >   drm/i915/config: Set general connector properties using config.
> >   drm/i915/config: Split out allocation of list nodes.
> >   drm/i915/config: Get workaround information from configuration.
> >   drm/i915/config: Use workarounds list from configuration.
> >   drm/i915/config: Add VBT settings configuration.
> >   drm/i915/config: Introduce a test table and code to make use of it.
> >   drm/i915/config: Add workaround properties to ACPI table.
> >   drm/i915/config: Add ACPI device examples for VBT configuration.
> >
> >  drivers/gpu/drm/i915/Makefile            |    3 +-
> >  drivers/gpu/drm/i915/i915-properties.asl |  340 ++++++++++
> >  drivers/gpu/drm/i915/i915-properties.hex |  409 ++++++++++++
> >  drivers/gpu/drm/i915/i915_dma.c          |    6 +
> >  drivers/gpu/drm/i915/i915_drv.h          |   18 +
> >  drivers/gpu/drm/i915/i915_params.c       |    6 +
> >  drivers/gpu/drm/i915/intel_config.c      | 1002 ++++++++++++++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_display.c     |   71 +++
> >  drivers/gpu/drm/i915/intel_dp.c          |    8 +-
> >  drivers/gpu/drm/i915/intel_drv.h         |   33 +
> >  drivers/gpu/drm/i915/intel_modes.c       |    8 +-
> >  drivers/gpu/drm/i915/intel_ringbuffer.c  |   19 +-
> >  12 files changed, 1909 insertions(+), 14 deletions(-)
> >  create mode 100644 drivers/gpu/drm/i915/i915-properties.asl
> >  create mode 100644 drivers/gpu/drm/i915/i915-properties.hex
> >  create mode 100644 drivers/gpu/drm/i915/intel_config.c
> >
> > -- 
> > 2.1.0
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 07/12] drm/i915/config: Get workaround information from configuration.
  2015-02-12 23:41 ` [RFC 07/12] drm/i915/config: Get workaround information from configuration Bob Paauwe
@ 2015-02-24 13:51   ` Daniel Vetter
  2015-02-24 17:54     ` Bob Paauwe
  0 siblings, 1 reply; 32+ messages in thread
From: Daniel Vetter @ 2015-02-24 13:51 UTC (permalink / raw)
  To: Bob Paauwe; +Cc: intel-gfx

On Thu, Feb 12, 2015 at 03:41:33PM -0800, Bob Paauwe wrote:
> Add ability to parse a list of workarounds from the ACPI table.
> Initially, this expects all workarounds listed to be valid and
> they replace the hard coded list initialized in init_workarounds_ring().
> 
> The main benefit of this is the ability to add/remove workarounds
> at runtime.  It may also be useful to "adjust" the workaround
> list for a new GPU prior to fixed support being available in the
> driver.
> 
> Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>

This one here freaks me out. We /should/ be fast enough with rolling out
workarounds through backports to stable kernels and product trees that
this shouldn't ever matter. And for a lot of workarounds this is too
limited since we also need to emit some of them to the ring on each engine
init or sometimes even context load.

As-is it looks a lot more like a backdoor to the driver to enable some
features no one wants to talk about in public ;-)
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_drv.h     |   1 +
>  drivers/gpu/drm/i915/intel_config.c | 101 +++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_drv.h    |   4 +-
>  3 files changed, 104 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 165091c..1580702 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1656,6 +1656,7 @@ struct intel_config_info {
>  	struct list_head crtc_list;
>  	struct list_head connector_list;
>  	struct list_head plane_list;
> +	struct list_head wa_list;
>  };
>  
>  
> diff --git a/drivers/gpu/drm/i915/intel_config.c b/drivers/gpu/drm/i915/intel_config.c
> index fb495ed..ab14928 100644
> --- a/drivers/gpu/drm/i915/intel_config.c
> +++ b/drivers/gpu/drm/i915/intel_config.c
> @@ -214,6 +214,7 @@ void intel_config_init(struct drm_device *dev)
>  	INIT_LIST_HEAD(&info->crtc_list);
>  	INIT_LIST_HEAD(&info->connector_list);
>  	INIT_LIST_HEAD(&info->plane_list);
> +	INIT_LIST_HEAD(&info->wa_list);
>  
>  	handle = ACPI_HANDLE(dev->dev);
>  	if (!handle) {
> @@ -239,6 +240,7 @@ void intel_config_init(struct drm_device *dev)
>  #define i915_COMPONENT_CRTC "CRTC"
>  #define i915_COMPONENT_CONNECTOR "CNCT"
>  #define i915_COMPONENT_PLANE "PLNS"
> +#define i915_COMPONENT_WORKAROUND "WRKS"
>  
>  	/* Build lists */
>  	list_for_each_entry(component, &info->base.adev->children, node) {
> @@ -262,6 +264,9 @@ void intel_config_init(struct drm_device *dev)
>  				if (!alloc_new_node(cl, &info->crtc_list))
>  					goto bail;
>  			}
> +		} else if (strcmp(cname, i915_COMPONENT_WORKAROUND) == 0) {
> +			if (!alloc_new_node(cl, &info->wa_list))
> +				goto bail;
>  		}
>  	}
>  
> @@ -277,6 +282,8 @@ bail:
>  		kfree(new_node);
>  	list_for_each_entry_safe(new_node, tmp, &info->plane_list, node)
>  		kfree(new_node);
> +	list_for_each_entry_safe(new_node, tmp, &info->wa_list, node)
> +		kfree(new_node);
>  
>  	kfree(info);
>  	dev_priv->config_info = NULL;
> @@ -309,6 +316,8 @@ void intel_config_shutdown(struct drm_device *dev)
>  		kfree(n);
>  	list_for_each_entry_safe(n, tmp, &info->plane_list, node)
>  		kfree(n);
> +	list_for_each_entry_safe(n, tmp, &info->wa_list, node)
> +		kfree(n);
>  
>  	/* Unload any dynamically loaded ACPI property table */
>  	handle = ACPI_HANDLE(dev->dev);
> @@ -384,6 +393,8 @@ static struct list_head *cfg_type_to_list(struct intel_config_info *info,
>  		return &info->connector_list;
>  	case CFG_PLANE:
>  		return &info->plane_list;
> +	case CFG_WORKAROUND:
> +		return &info->wa_list;
>  	}
>  	return NULL;
>  }
> @@ -404,7 +415,6 @@ bool intel_config_get_integer(struct drm_i915_private *dev_priv,
>  	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;
> @@ -423,6 +433,95 @@ bool intel_config_get_integer(struct drm_i915_private *dev_priv,
>  	return false;
>  }
>  
> +
> +/*
> + * Use ACPI methods to enumerate the items in the WA list.
> + *
> + * The list from the ACPI table is inserted into the ring_init
> + * workaround table.  This could either over-wright any hard coded
> + * table or append to an existing hard coded table. Need to understand
> + * which way would make more sense.
> + */
> +bool intel_config_wa_add(struct drm_i915_private *dev_priv)
> +{
> +	struct intel_config_info *info = dev_priv->config_info;
> +	const union acpi_object *properties;
> +	const union acpi_object *prop, *name, *value;
> +	struct list_head *list;
> +	struct intel_config_node *n;
> +	int i;
> +	u32 idx;
> +	bool ret = false;
> +
> +	list = cfg_type_to_list(info, CFG_WORKAROUND);
> +	if (!list)
> +		return false;
> +
> +	list_for_each_entry(n, list, node) {
> +		properties = n->adev->data.properties;
> +		if (!properties)
> +			continue;
> +
> +		DRM_DEBUG_DRIVER("i915/config/wa: Found %d workarounds\n",
> +					properties->package.count);
> +
> +		for (i = 0; i < properties->package.count; i++) {
> +			prop = &properties->package.elements[i];
> +			name = &prop->package.elements[0];
> +			value = &prop->package.elements[1];
> +			ret = true;
> +
> +			/*
> +			 * Right now, it's assumed that any workarounds
> +			 * listed in the table should be added to the
> +			 * workaround array and applied. This could be a
> +			 * bad assumption.
> +			 *
> +			 * Might be better if the workaround table includes
> +			 * the PCI ID and check that before applying.
> +			 */
> +
> +			if ((value->package.count >= 2) &&
> +			    (value->type == ACPI_TYPE_PACKAGE)) {
> +				/*
> +				 * Package elements:
> +				 *   0 = workaround register
> +				 *   1 = register value
> +				 *   2 = mask
> +				 *   3 = mask enable vs disable bit (flags)
> +				 */
> +				idx = dev_priv->workarounds.count;
> +				if (WARN_ON(idx >= I915_MAX_WA_REGS))
> +					return ret;
> +
> +				dev_priv->workarounds.reg[idx].addr =
> +					(u32)value->package.elements[0].integer.value;
> +				dev_priv->workarounds.reg[idx].value =
> +					(u32)value->package.elements[1].integer.value;
> +
> +				if ((u32)value->package.elements[3].integer.value)
> +					dev_priv->workarounds.reg[idx].mask =
> +						_MASKED_BIT_ENABLE(
> +								(u32)value->package.elements[2].integer.value);
> +				else
> +					dev_priv->workarounds.reg[idx].mask =
> +						_MASKED_BIT_DISABLE(
> +								(u32)value->package.elements[2].integer.value);
> +
> +				dev_priv->workarounds.count++;
> +
> +				DRM_DEBUG_DRIVER("i915/config: WA %s = 0x%x, 0x%x, 0x%x\n",
> +					   name->string.pointer,
> +					   dev_priv->workarounds.reg[idx].addr,
> +					   dev_priv->workarounds.reg[idx].value,
> +					   dev_priv->workarounds.reg[idx].mask);
> +			}
> +		}
> +	}
> +
> +	return ret;
> +}
> +
>  /*
>   * Look up a drm property name in the configuration store and if
>   * found, return the value.
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 4c81ee9..e2b4e09 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1265,11 +1265,13 @@ enum cfg_type {
>  	CFG_DRV,
>  	CFG_CRTC,
>  	CFG_CONNECTOR,
> -	CFG_PLANE
> +	CFG_PLANE,
> +	CFG_WORKAROUND
>  };
>  
>  void intel_config_init(struct drm_device *dev);
>  void intel_config_shutdown(struct drm_device *dev);
> +bool intel_config_wa_add(struct drm_i915_private *dev_priv);
>  bool intel_config_get_integer(struct drm_i915_private *dev_priv,
>  			  enum cfg_type cfg_type,
>  			  const char *name,
> -- 
> 2.1.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@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
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 09/12] drm/i915/config: Add VBT settings configuration.
  2015-02-12 23:41 ` [RFC 09/12] drm/i915/config: Add VBT settings configuration Bob Paauwe
@ 2015-02-24 13:57   ` Daniel Vetter
  2015-02-24 18:37     ` Bob Paauwe
  0 siblings, 1 reply; 32+ messages in thread
From: Daniel Vetter @ 2015-02-24 13:57 UTC (permalink / raw)
  To: Bob Paauwe; +Cc: intel-gfx

On Thu, Feb 12, 2015 at 03:41:35PM -0800, Bob Paauwe wrote:
> Add a new section with subsections to the ACPI configuration table
> that mimics much of the information typically stored in the VBT/option
> ROM. This allows for a way to override incorrect VBT data or to provide
> the configuration if VBT is not present.  Lack of VBT is common in
> embedded systems.
> 
> Any data found in the configuration tables will replace the driver's
> vbt structure.
> 
> MIPI DSI configuration is not implmemnted at this time.
> 
> Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>

I'm not too happy with the duplicate of standards this creates. Is there
no way to just load a vbt blob into the acpi table somewhere and require
that it perfectly matches the vbt "standard" for the given platforms,
warts and all included?

As Jani points out we already have vbt headaches, it would be good if we
only have those once ;-)
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_dma.c     |   2 +
>  drivers/gpu/drm/i915/i915_drv.h     |   1 +
>  drivers/gpu/drm/i915/intel_config.c | 334 ++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h    |   4 +-
>  4 files changed, 340 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 9501360..9119e9b 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -852,6 +852,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  	if (intel_vgpu_active(dev))
>  		I915_WRITE(vgtif_reg(display_ready), VGT_DRV_DISPLAY_READY);
>  
> +	intel_config_vbt(dev_priv);
> +
>  	i915_setup_sysfs(dev);
>  
>  	if (INTEL_INFO(dev)->num_pipes) {
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 1580702..a60511e 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1657,6 +1657,7 @@ struct intel_config_info {
>  	struct list_head connector_list;
>  	struct list_head plane_list;
>  	struct list_head wa_list;
> +	struct list_head vbt_list;
>  };
>  
>  
> diff --git a/drivers/gpu/drm/i915/intel_config.c b/drivers/gpu/drm/i915/intel_config.c
> index ab14928..c1b06b7 100644
> --- a/drivers/gpu/drm/i915/intel_config.c
> +++ b/drivers/gpu/drm/i915/intel_config.c
> @@ -215,6 +215,7 @@ void intel_config_init(struct drm_device *dev)
>  	INIT_LIST_HEAD(&info->connector_list);
>  	INIT_LIST_HEAD(&info->plane_list);
>  	INIT_LIST_HEAD(&info->wa_list);
> +	INIT_LIST_HEAD(&info->vbt_list);
>  
>  	handle = ACPI_HANDLE(dev->dev);
>  	if (!handle) {
> @@ -241,6 +242,7 @@ void intel_config_init(struct drm_device *dev)
>  #define i915_COMPONENT_CONNECTOR "CNCT"
>  #define i915_COMPONENT_PLANE "PLNS"
>  #define i915_COMPONENT_WORKAROUND "WRKS"
> +#define i915_COMPONENT_VBIOSTABLE "VBT"
>  
>  	/* Build lists */
>  	list_for_each_entry(component, &info->base.adev->children, node) {
> @@ -267,6 +269,18 @@ void intel_config_init(struct drm_device *dev)
>  		} else if (strcmp(cname, i915_COMPONENT_WORKAROUND) == 0) {
>  			if (!alloc_new_node(cl, &info->wa_list))
>  				goto bail;
> +		} else if (strcmp(cname, i915_COMPONENT_VBIOSTABLE) == 0) {
> +			/* Add the main VBT node */
> +			if (!alloc_new_node(cl, &info->vbt_list))
> +				goto bail;
> +
> +			/* This adds all the sub device nodes */
> +			list_for_each_entry(cl, &component->children, node) {
> +				if (!alloc_new_node(cl, &info->vbt_list))
> +					goto bail;
> +			}
> +		} else {
> +			DRM_DEBUG_DRIVER("i915/config: Unknown component : %s\n", cname);
>  		}
>  	}
>  
> @@ -284,6 +298,8 @@ bail:
>  		kfree(new_node);
>  	list_for_each_entry_safe(new_node, tmp, &info->wa_list, node)
>  		kfree(new_node);
> +	list_for_each_entry_safe(new_node, tmp, &info->vbt_list, node)
> +		kfree(new_node);
>  
>  	kfree(info);
>  	dev_priv->config_info = NULL;
> @@ -318,6 +334,8 @@ void intel_config_shutdown(struct drm_device *dev)
>  		kfree(n);
>  	list_for_each_entry_safe(n, tmp, &info->wa_list, node)
>  		kfree(n);
> +	list_for_each_entry_safe(n, tmp, &info->vbt_list, node)
> +		kfree(n);
>  
>  	/* Unload any dynamically loaded ACPI property table */
>  	handle = ACPI_HANDLE(dev->dev);
> @@ -395,6 +413,8 @@ static struct list_head *cfg_type_to_list(struct intel_config_info *info,
>  		return &info->plane_list;
>  	case CFG_WORKAROUND:
>  		return &info->wa_list;
> +	case CFG_VBT:
> +		return &info->vbt_list;
>  	}
>  	return NULL;
>  }
> @@ -433,6 +453,320 @@ bool intel_config_get_integer(struct drm_i915_private *dev_priv,
>  	return false;
>  }
>  
> +static void parse_port_info(struct drm_i915_private *dev_priv,
> +			    const union acpi_object *pkg,
> +			    int port)
> +{
> +	u32 supports;
> +
> +	if (pkg->type != ACPI_TYPE_PACKAGE)
> +		return;
> +
> +	dev_priv->vbt.ddi_port_info[port].hdmi_level_shift =
> +		(u32)pkg->package.elements[0].integer.value;
> +
> +	supports = (u32)pkg->package.elements[1].integer.value;
> +	dev_priv->vbt.ddi_port_info[port].supports_dvi  = supports & 0x01;
> +	dev_priv->vbt.ddi_port_info[port].supports_hdmi = supports & 0x02;
> +	dev_priv->vbt.ddi_port_info[port].supports_dp   = supports & 0x04;
> +}
> +
> +static struct drm_display_mode *parse_mode_info(const union acpi_object *pkg)
> +{
> +	struct drm_display_mode *mode;
> +
> +	if (pkg->type != ACPI_TYPE_PACKAGE)
> +		return NULL;
> +
> +	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
> +	if (!mode || pkg->package.count != 10)
> +		return NULL;
> +
> +	mode->hdisplay = (u32)pkg->package.elements[0].integer.value;
> +	mode->hsync_start = (u32)pkg->package.elements[1].integer.value;
> +	mode->hsync_end = (u32)pkg->package.elements[3].integer.value;
> +	mode->htotal = (u32)pkg->package.elements[3].integer.value;
> +	mode->vdisplay = (u32)pkg->package.elements[4].integer.value;
> +	mode->vsync_start = (u32)pkg->package.elements[5].integer.value;
> +	mode->vsync_end = (u32)pkg->package.elements[6].integer.value;
> +	mode->vtotal = (u32)pkg->package.elements[7].integer.value;
> +	mode->clock = (u32)pkg->package.elements[8].integer.value;
> +	mode->flags = (u32)pkg->package.elements[9].integer.value;
> +	mode->type = DRM_MODE_TYPE_PREFERRED;
> +
> +	return mode;
> +}
> +
> +
> +#define PROPERTY_MATCH(prop, name)\
> +	(strcasecmp(prop->string.pointer, name) == 0)
> +
> +/*
> + * Set any general vbt features defined in the ACPI table.
> + */
> +static void parse_vbt_general(struct drm_i915_private *dev_priv,
> +			      const union acpi_object *properties,
> +			      struct acpi_device *adev)
> +{
> +	const union acpi_object *prop, *name, *value;
> +	int i;
> +
> +	for (i = 0; i < properties->package.count; i++) {
> +		prop = &properties->package.elements[i];
> +		name = &prop->package.elements[0];
> +		value = &prop->package.elements[1];
> +
> +		if (PROPERTY_MATCH(name, "Internal TV"))
> +			dev_priv->vbt.int_tv_support =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "Internal CRT"))
> +			dev_priv->vbt.int_crt_support =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "port info A"))
> +			parse_port_info(dev_priv, value, PORT_A);
> +		else if (PROPERTY_MATCH(name, "port info B"))
> +			parse_port_info(dev_priv, value, PORT_B);
> +		else if (PROPERTY_MATCH(name, "port info C"))
> +			parse_port_info(dev_priv, value, PORT_C);
> +		else if (PROPERTY_MATCH(name, "port info D"))
> +			parse_port_info(dev_priv, value, PORT_D);
> +		else if (PROPERTY_MATCH(name, "port info E"))
> +			parse_port_info(dev_priv, value, PORT_E);
> +		else if (PROPERTY_MATCH(name, "crt ddc pin"))
> +			dev_priv->vbt.crt_ddc_pin = (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "drrs type"))
> +			dev_priv->vbt.drrs_type = (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "fdi rx polarity inverted"))
> +			dev_priv->vbt.fdi_rx_polarity_inverted =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "display clock mode"))
> +			dev_priv->vbt.display_clock_mode =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "mode"))
> +			dev_priv->vbt.lfp_lvds_vbt_mode =
> +			    parse_mode_info(value);
> +	}
> +}
> +
> +static void parse_vbt_lvds(struct drm_i915_private *dev_priv,
> +			   const union acpi_object *properties,
> +			   struct acpi_device *adev)
> +{
> +	const union acpi_object *prop, *name, *value;
> +	int i;
> +
> +	for (i = 0; i < properties->package.count; i++) {
> +		prop = &properties->package.elements[i];
> +		name = &prop->package.elements[0];
> +		value = &prop->package.elements[1];
> +
> +		if (PROPERTY_MATCH(name, "lvds use ssc"))
> +			dev_priv->vbt.lvds_use_ssc = (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "LVDS SSC Freq"))
> +			dev_priv->vbt.lvds_ssc_freq =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "lvds downclock avail"))
> +			dev_priv->lvds_downclock_avail =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "lvds downclock"))
> +			dev_priv->lvds_downclock = (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "Pixel Dither"))
> +			dev_priv->vbt.lvds_dither = (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "bios lvds val"))
> +			dev_priv->vbt.bios_lvds_val =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "lvds vbt"))
> +			dev_priv->vbt.lvds_vbt = (u32)value->integer.value;
> +	}
> +}
> +
> +static void parse_pwsq(struct drm_i915_private *dev_priv,
> +		       const union acpi_object *properties)
> +{
> +	const union acpi_object *prop, *name, *value;
> +	int i;
> +
> +	for (i = 0; i < properties->package.count; i++) {
> +		prop = &properties->package.elements[i];
> +		name = &prop->package.elements[0];
> +		value = &prop->package.elements[1];
> +
> +		if (PROPERTY_MATCH(name, "t1/t3"))
> +			dev_priv->vbt.edp_pps.t1_t3 =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "t8"))
> +			dev_priv->vbt.edp_pps.t8 = (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "t9"))
> +			dev_priv->vbt.edp_pps.t9 = (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "t10"))
> +			dev_priv->vbt.edp_pps.t10 = (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "t11/t12"))
> +			dev_priv->vbt.edp_pps.t11_t12 =
> +			    (u32)value->integer.value;
> +	}
> +}
> +
> +static void parse_backlight(struct drm_i915_private *dev_priv,
> +			    const union acpi_object *properties)
> +{
> +	const union acpi_object *prop, *name, *value;
> +	int i;
> +
> +	for (i = 0; i < properties->package.count; i++) {
> +		prop = &properties->package.elements[i];
> +		name = &prop->package.elements[0];
> +		value = &prop->package.elements[1];
> +
> +		if (PROPERTY_MATCH(name, "present"))
> +			dev_priv->vbt.backlight.present =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "pwm freq hz"))
> +			dev_priv->vbt.backlight.pwm_freq_hz =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "active low pwm"))
> +			dev_priv->vbt.backlight.active_low_pwm =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "min brightness"))
> +			dev_priv->vbt.backlight.min_brightness =
> +			    (u32)value->integer.value;
> +	}
> +}
> +
> +static void parse_psr(struct drm_i915_private *dev_priv,
> +		      const union acpi_object *properties)
> +{
> +	const union acpi_object *prop, *name, *value;
> +	int i;
> +
> +	for (i = 0; i < properties->package.count; i++) {
> +		prop = &properties->package.elements[i];
> +		name = &prop->package.elements[0];
> +		value = &prop->package.elements[1];
> +
> +		if (PROPERTY_MATCH(name, "full link"))
> +			dev_priv->vbt.psr.full_link =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "require aux wakeup"))
> +			dev_priv->vbt.psr.require_aux_wakeup =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "idle frames"))
> +			dev_priv->vbt.psr.idle_frames =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "lines to wait"))
> +			dev_priv->vbt.psr.lines_to_wait =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "tp1 wakeup time"))
> +			dev_priv->vbt.psr.tp1_wakeup_time =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "tp2 tp3 wakeup time"))
> +			dev_priv->vbt.psr.tp2_tp3_wakeup_time =
> +			    (u32)value->integer.value;
> +	}
> +}
> +
> +static void parse_vbt_edp(struct drm_i915_private *dev_priv,
> +			  const union acpi_object *properties,
> +			  struct acpi_device *adev)
> +{
> +	const union acpi_object *prop, *name, *value;
> +	int i;
> +	struct acpi_device *component;
> +
> +	/* Child devices for Power sequencing, PSR and Backlight */
> +	list_for_each_entry(component, &adev->children, node) {
> +		char *sub_section_name;
> +		const union acpi_object *properties;
> +
> +		if (!component)
> +			continue;
> +
> +		sub_section_name = acpi_device_bid(component);
> +		properties = component->data.properties;
> +
> +		if (!properties)
> +			continue;
> +
> +		if (strcmp(sub_section_name, "PWSQ") == 0)
> +			parse_pwsq(dev_priv, properties);
> +		else if (strcmp(sub_section_name, "BLKT") == 0)
> +			parse_backlight(dev_priv, properties);
> +		else if (strcmp(sub_section_name, "PSR") == 0)
> +			parse_psr(dev_priv, properties);
> +	}
> +
> +	/* Process any EDP port configuration  */
> +	for (i = 0; i < properties->package.count; i++) {
> +		prop = &properties->package.elements[i];
> +		name = &prop->package.elements[0];
> +		value = &prop->package.elements[1];
> +
> +		if (PROPERTY_MATCH(name, "edp bpp"))
> +			dev_priv->vbt.edp_bpp = (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "edp pps")) {
> +			/*
> +			 * The power sequence timing values are stored in
> +			 * an array
> +			 */
> +			dev_priv->vbt.edp_pps.t1_t3 =
> +				(u32)value->package.elements[0].integer.value;
> +			dev_priv->vbt.edp_pps.t8 =
> +				(u32)value->package.elements[1].integer.value;
> +			dev_priv->vbt.edp_pps.t9 =
> +				(u32)value->package.elements[2].integer.value;
> +			dev_priv->vbt.edp_pps.t10 =
> +				(u32)value->package.elements[3].integer.value;
> +			dev_priv->vbt.edp_pps.t11_t12 =
> +				(u32)value->package.elements[4].integer.value;
> +		} else if (PROPERTY_MATCH(name, "edp rate"))
> +			dev_priv->vbt.edp_rate = (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "edp lanes"))
> +			dev_priv->vbt.edp_lanes = (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "edp preemphasis"))
> +			dev_priv->vbt.edp_preemphasis =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "edp vswing"))
> +			dev_priv->vbt.edp_vswing = (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "edp initialized"))
> +			dev_priv->vbt.edp_initialized =
> +			    (u32)value->integer.value;
> +		else if (PROPERTY_MATCH(name, "edp support"))
> +			dev_priv->vbt.edp_support = (u32)value->integer.value;
> +	}
> +}
> +
> +/*
> + * Port device configration based on VBT.
> + *
> + * Use the configuration information to overwrite any
> + * corresponding VBT values or provide initial configuration
> + * if VBT doens't exist.
> + */
> +void intel_config_vbt(struct drm_i915_private *dev_priv)
> +{
> +	struct intel_config_info *info = dev_priv->config_info;
> +	const union acpi_object *properties;
> +	struct list_head *list;
> +	struct intel_config_node *n;
> +	char *sub_section_name;
> +
> +	list = cfg_type_to_list(info, CFG_VBT);
> +	list_for_each_entry(n, list, node) {
> +		sub_section_name = acpi_device_bid(n->adev);
> +		properties = n->adev->data.properties;
> +		if (!properties)
> +			continue;
> +
> +		/* Call into sub section handlers */
> +		if (strcmp(sub_section_name, "VBT") == 0)
> +			parse_vbt_general(dev_priv, properties, n->adev);
> +		else if (strcmp(sub_section_name, "LVDS") == 0)
> +			parse_vbt_lvds(dev_priv, properties, n->adev);
> +		else if (strcmp(sub_section_name, "EDP") == 0)
> +			parse_vbt_edp(dev_priv, properties, n->adev);
> +		else if (strcmp(sub_section_name, "DSI") == 0)
> +			DRM_DEBUG_DRIVER("i915/config/vbt: Process Mipi DSI VBT features\n");
> +	}
> +}
>  
>  /*
>   * Use ACPI methods to enumerate the items in the WA list.
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index e2b4e09..cc5da99 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1266,12 +1266,14 @@ enum cfg_type {
>  	CFG_CRTC,
>  	CFG_CONNECTOR,
>  	CFG_PLANE,
> -	CFG_WORKAROUND
> +	CFG_WORKAROUND,
> +	CFG_VBT
>  };
>  
>  void intel_config_init(struct drm_device *dev);
>  void intel_config_shutdown(struct drm_device *dev);
>  bool intel_config_wa_add(struct drm_i915_private *dev_priv);
> +void intel_config_vbt(struct drm_i915_private *dev_priv);
>  bool intel_config_get_integer(struct drm_i915_private *dev_priv,
>  			  enum cfg_type cfg_type,
>  			  const char *name,
> -- 
> 2.1.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@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
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 01/12] drm/i915/config: Initial framework
  2015-02-12 23:41 ` [RFC 01/12] drm/i915/config: Initial framework Bob Paauwe
  2015-02-13  8:19   ` Jani Nikula
@ 2015-02-24 16:17   ` Daniel Vetter
  2015-02-24 17:41     ` Bob Paauwe
  1 sibling, 1 reply; 32+ messages in thread
From: Daniel Vetter @ 2015-02-24 16:17 UTC (permalink / raw)
  To: Bob Paauwe; +Cc: intel-gfx

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@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@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
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 01/12] drm/i915/config: Initial framework
  2015-02-24 16:17   ` Daniel Vetter
@ 2015-02-24 17:41     ` Bob Paauwe
  2015-02-24 20:47       ` Daniel Vetter
  0 siblings, 1 reply; 32+ messages in thread
From: Bob Paauwe @ 2015-02-24 17:41 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Tue, 24 Feb 2015 17:17:18 +0100
Daniel Vetter <daniel@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@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@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 07/12] drm/i915/config: Get workaround information from configuration.
  2015-02-24 13:51   ` Daniel Vetter
@ 2015-02-24 17:54     ` Bob Paauwe
  0 siblings, 0 replies; 32+ messages in thread
From: Bob Paauwe @ 2015-02-24 17:54 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Tue, 24 Feb 2015 14:51:31 +0100
Daniel Vetter <daniel@ffwll.ch> wrote:

> On Thu, Feb 12, 2015 at 03:41:33PM -0800, Bob Paauwe wrote:
> > Add ability to parse a list of workarounds from the ACPI table.
> > Initially, this expects all workarounds listed to be valid and
> > they replace the hard coded list initialized in init_workarounds_ring().
> > 
> > The main benefit of this is the ability to add/remove workarounds
> > at runtime.  It may also be useful to "adjust" the workaround
> > list for a new GPU prior to fixed support being available in the
> > driver.
> > 
> > Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
> 
> This one here freaks me out. We /should/ be fast enough with rolling out
> workarounds through backports to stable kernels and product trees that
> this shouldn't ever matter. And for a lot of workarounds this is too
> limited since we also need to emit some of them to the ring on each engine
> init or sometimes even context load.
> 
> As-is it looks a lot more like a backdoor to the driver to enable some
> features no one wants to talk about in public ;-)
> -Daniel

Yeah, I don't know that we have any valid use-case for this.  It
really is just an idea. Maybe a bad idea. It was something that looked
like it could map into the configuration space so I coded it up. 

I did think it might be useful if we could disable workarounds for early
steppings that may not be applicable for later steppings without the
need to release a new version of the driver.  As it sits, it doesn't
support this use-case so would need a bit more work. For some embedded
appliance type devices, customers are sometimes more willing to take a
configuration change than a new driver.

The patches for this should be easy to drop without effecting anything
else.

> 
> > ---
> >  drivers/gpu/drm/i915/i915_drv.h     |   1 +
> >  drivers/gpu/drm/i915/intel_config.c | 101 +++++++++++++++++++++++++++++++++++-
> >  drivers/gpu/drm/i915/intel_drv.h    |   4 +-
> >  3 files changed, 104 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 165091c..1580702 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1656,6 +1656,7 @@ struct intel_config_info {
> >  	struct list_head crtc_list;
> >  	struct list_head connector_list;
> >  	struct list_head plane_list;
> > +	struct list_head wa_list;
> >  };
> >  
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_config.c b/drivers/gpu/drm/i915/intel_config.c
> > index fb495ed..ab14928 100644
> > --- a/drivers/gpu/drm/i915/intel_config.c
> > +++ b/drivers/gpu/drm/i915/intel_config.c
> > @@ -214,6 +214,7 @@ void intel_config_init(struct drm_device *dev)
> >  	INIT_LIST_HEAD(&info->crtc_list);
> >  	INIT_LIST_HEAD(&info->connector_list);
> >  	INIT_LIST_HEAD(&info->plane_list);
> > +	INIT_LIST_HEAD(&info->wa_list);
> >  
> >  	handle = ACPI_HANDLE(dev->dev);
> >  	if (!handle) {
> > @@ -239,6 +240,7 @@ void intel_config_init(struct drm_device *dev)
> >  #define i915_COMPONENT_CRTC "CRTC"
> >  #define i915_COMPONENT_CONNECTOR "CNCT"
> >  #define i915_COMPONENT_PLANE "PLNS"
> > +#define i915_COMPONENT_WORKAROUND "WRKS"
> >  
> >  	/* Build lists */
> >  	list_for_each_entry(component, &info->base.adev->children, node) {
> > @@ -262,6 +264,9 @@ void intel_config_init(struct drm_device *dev)
> >  				if (!alloc_new_node(cl, &info->crtc_list))
> >  					goto bail;
> >  			}
> > +		} else if (strcmp(cname, i915_COMPONENT_WORKAROUND) == 0) {
> > +			if (!alloc_new_node(cl, &info->wa_list))
> > +				goto bail;
> >  		}
> >  	}
> >  
> > @@ -277,6 +282,8 @@ bail:
> >  		kfree(new_node);
> >  	list_for_each_entry_safe(new_node, tmp, &info->plane_list, node)
> >  		kfree(new_node);
> > +	list_for_each_entry_safe(new_node, tmp, &info->wa_list, node)
> > +		kfree(new_node);
> >  
> >  	kfree(info);
> >  	dev_priv->config_info = NULL;
> > @@ -309,6 +316,8 @@ void intel_config_shutdown(struct drm_device *dev)
> >  		kfree(n);
> >  	list_for_each_entry_safe(n, tmp, &info->plane_list, node)
> >  		kfree(n);
> > +	list_for_each_entry_safe(n, tmp, &info->wa_list, node)
> > +		kfree(n);
> >  
> >  	/* Unload any dynamically loaded ACPI property table */
> >  	handle = ACPI_HANDLE(dev->dev);
> > @@ -384,6 +393,8 @@ static struct list_head *cfg_type_to_list(struct intel_config_info *info,
> >  		return &info->connector_list;
> >  	case CFG_PLANE:
> >  		return &info->plane_list;
> > +	case CFG_WORKAROUND:
> > +		return &info->wa_list;
> >  	}
> >  	return NULL;
> >  }
> > @@ -404,7 +415,6 @@ bool intel_config_get_integer(struct drm_i915_private *dev_priv,
> >  	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;
> > @@ -423,6 +433,95 @@ bool intel_config_get_integer(struct drm_i915_private *dev_priv,
> >  	return false;
> >  }
> >  
> > +
> > +/*
> > + * Use ACPI methods to enumerate the items in the WA list.
> > + *
> > + * The list from the ACPI table is inserted into the ring_init
> > + * workaround table.  This could either over-wright any hard coded
> > + * table or append to an existing hard coded table. Need to understand
> > + * which way would make more sense.
> > + */
> > +bool intel_config_wa_add(struct drm_i915_private *dev_priv)
> > +{
> > +	struct intel_config_info *info = dev_priv->config_info;
> > +	const union acpi_object *properties;
> > +	const union acpi_object *prop, *name, *value;
> > +	struct list_head *list;
> > +	struct intel_config_node *n;
> > +	int i;
> > +	u32 idx;
> > +	bool ret = false;
> > +
> > +	list = cfg_type_to_list(info, CFG_WORKAROUND);
> > +	if (!list)
> > +		return false;
> > +
> > +	list_for_each_entry(n, list, node) {
> > +		properties = n->adev->data.properties;
> > +		if (!properties)
> > +			continue;
> > +
> > +		DRM_DEBUG_DRIVER("i915/config/wa: Found %d workarounds\n",
> > +					properties->package.count);
> > +
> > +		for (i = 0; i < properties->package.count; i++) {
> > +			prop = &properties->package.elements[i];
> > +			name = &prop->package.elements[0];
> > +			value = &prop->package.elements[1];
> > +			ret = true;
> > +
> > +			/*
> > +			 * Right now, it's assumed that any workarounds
> > +			 * listed in the table should be added to the
> > +			 * workaround array and applied. This could be a
> > +			 * bad assumption.
> > +			 *
> > +			 * Might be better if the workaround table includes
> > +			 * the PCI ID and check that before applying.
> > +			 */
> > +
> > +			if ((value->package.count >= 2) &&
> > +			    (value->type == ACPI_TYPE_PACKAGE)) {
> > +				/*
> > +				 * Package elements:
> > +				 *   0 = workaround register
> > +				 *   1 = register value
> > +				 *   2 = mask
> > +				 *   3 = mask enable vs disable bit (flags)
> > +				 */
> > +				idx = dev_priv->workarounds.count;
> > +				if (WARN_ON(idx >= I915_MAX_WA_REGS))
> > +					return ret;
> > +
> > +				dev_priv->workarounds.reg[idx].addr =
> > +					(u32)value->package.elements[0].integer.value;
> > +				dev_priv->workarounds.reg[idx].value =
> > +					(u32)value->package.elements[1].integer.value;
> > +
> > +				if ((u32)value->package.elements[3].integer.value)
> > +					dev_priv->workarounds.reg[idx].mask =
> > +						_MASKED_BIT_ENABLE(
> > +								(u32)value->package.elements[2].integer.value);
> > +				else
> > +					dev_priv->workarounds.reg[idx].mask =
> > +						_MASKED_BIT_DISABLE(
> > +								(u32)value->package.elements[2].integer.value);
> > +
> > +				dev_priv->workarounds.count++;
> > +
> > +				DRM_DEBUG_DRIVER("i915/config: WA %s = 0x%x, 0x%x, 0x%x\n",
> > +					   name->string.pointer,
> > +					   dev_priv->workarounds.reg[idx].addr,
> > +					   dev_priv->workarounds.reg[idx].value,
> > +					   dev_priv->workarounds.reg[idx].mask);
> > +			}
> > +		}
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> >  /*
> >   * Look up a drm property name in the configuration store and if
> >   * found, return the value.
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 4c81ee9..e2b4e09 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1265,11 +1265,13 @@ enum cfg_type {
> >  	CFG_DRV,
> >  	CFG_CRTC,
> >  	CFG_CONNECTOR,
> > -	CFG_PLANE
> > +	CFG_PLANE,
> > +	CFG_WORKAROUND
> >  };
> >  
> >  void intel_config_init(struct drm_device *dev);
> >  void intel_config_shutdown(struct drm_device *dev);
> > +bool intel_config_wa_add(struct drm_i915_private *dev_priv);
> >  bool intel_config_get_integer(struct drm_i915_private *dev_priv,
> >  			  enum cfg_type cfg_type,
> >  			  const char *name,
> > -- 
> > 2.1.0
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 09/12] drm/i915/config: Add VBT settings configuration.
  2015-02-24 13:57   ` Daniel Vetter
@ 2015-02-24 18:37     ` Bob Paauwe
  2015-02-24 20:52       ` Daniel Vetter
  0 siblings, 1 reply; 32+ messages in thread
From: Bob Paauwe @ 2015-02-24 18:37 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Tue, 24 Feb 2015 14:57:48 +0100
Daniel Vetter <daniel@ffwll.ch> wrote:

> On Thu, Feb 12, 2015 at 03:41:35PM -0800, Bob Paauwe wrote:
> > Add a new section with subsections to the ACPI configuration table
> > that mimics much of the information typically stored in the VBT/option
> > ROM. This allows for a way to override incorrect VBT data or to provide
> > the configuration if VBT is not present.  Lack of VBT is common in
> > embedded systems.
> > 
> > Any data found in the configuration tables will replace the driver's
> > vbt structure.
> > 
> > MIPI DSI configuration is not implmemnted at this time.
> > 
> > Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com>
> 
> I'm not too happy with the duplicate of standards this creates. Is there
> no way to just load a vbt blob into the acpi table somewhere and require
> that it perfectly matches the vbt "standard" for the given platforms,
> warts and all included?

That's actually fairly easy to do. I believe that the opregion code is
just that. So the existing vbt code in the driver does that today.  The
acpi property code can't have an opregion embedded as a property, I did
look into that, but you can still create array properties and one of
those could hold a vbt blob. Another alternative would be to have a
property array for each vbt section. 

What I was trying for here was a way to override the driver defaults
for specific settings in the case where the platform did not have an
ACPI opregion or boot firmware with a vbt table.   I wasn't really
trying to create a mechanism to create an entire vbt table.  But the
parsing of the properties does get pretty messy.

> 
> As Jani points out we already have vbt headaches, it would be good if we
> only have those once ;-)
> -Daniel

I've been trying to think of a better way but not really coming up with
something that scales well. EMGD took the approach of create
configuration for only those values that we had customer requests for.
And that was primarily just the panel power up/down timing sequence and
some backlight control. We never tried to replicate everything that
could be set via vbt.

I've also been looking at splitting up the existing vbt structure in
some way so that both the exiting vbt code and the configuration code
could be used to set component configuration.  Something like 

  set_crt_ddc_pin() in the intel_crt code that gets called by either
  (or both) the vbt parsing code or the configuration framework.

But creating set_<something> functions for all the existing values in
the vbt structure seems like it might be too much overhead.

Bob

> 
> > ---
> >  drivers/gpu/drm/i915/i915_dma.c     |   2 +
> >  drivers/gpu/drm/i915/i915_drv.h     |   1 +
> >  drivers/gpu/drm/i915/intel_config.c | 334 ++++++++++++++++++++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_drv.h    |   4 +-
> >  4 files changed, 340 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> > index 9501360..9119e9b 100644
> > --- a/drivers/gpu/drm/i915/i915_dma.c
> > +++ b/drivers/gpu/drm/i915/i915_dma.c
> > @@ -852,6 +852,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
> >  	if (intel_vgpu_active(dev))
> >  		I915_WRITE(vgtif_reg(display_ready), VGT_DRV_DISPLAY_READY);
> >  
> > +	intel_config_vbt(dev_priv);
> > +
> >  	i915_setup_sysfs(dev);
> >  
> >  	if (INTEL_INFO(dev)->num_pipes) {
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 1580702..a60511e 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1657,6 +1657,7 @@ struct intel_config_info {
> >  	struct list_head connector_list;
> >  	struct list_head plane_list;
> >  	struct list_head wa_list;
> > +	struct list_head vbt_list;
> >  };
> >  
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_config.c b/drivers/gpu/drm/i915/intel_config.c
> > index ab14928..c1b06b7 100644
> > --- a/drivers/gpu/drm/i915/intel_config.c
> > +++ b/drivers/gpu/drm/i915/intel_config.c
> > @@ -215,6 +215,7 @@ void intel_config_init(struct drm_device *dev)
> >  	INIT_LIST_HEAD(&info->connector_list);
> >  	INIT_LIST_HEAD(&info->plane_list);
> >  	INIT_LIST_HEAD(&info->wa_list);
> > +	INIT_LIST_HEAD(&info->vbt_list);
> >  
> >  	handle = ACPI_HANDLE(dev->dev);
> >  	if (!handle) {
> > @@ -241,6 +242,7 @@ void intel_config_init(struct drm_device *dev)
> >  #define i915_COMPONENT_CONNECTOR "CNCT"
> >  #define i915_COMPONENT_PLANE "PLNS"
> >  #define i915_COMPONENT_WORKAROUND "WRKS"
> > +#define i915_COMPONENT_VBIOSTABLE "VBT"
> >  
> >  	/* Build lists */
> >  	list_for_each_entry(component, &info->base.adev->children, node) {
> > @@ -267,6 +269,18 @@ void intel_config_init(struct drm_device *dev)
> >  		} else if (strcmp(cname, i915_COMPONENT_WORKAROUND) == 0) {
> >  			if (!alloc_new_node(cl, &info->wa_list))
> >  				goto bail;
> > +		} else if (strcmp(cname, i915_COMPONENT_VBIOSTABLE) == 0) {
> > +			/* Add the main VBT node */
> > +			if (!alloc_new_node(cl, &info->vbt_list))
> > +				goto bail;
> > +
> > +			/* This adds all the sub device nodes */
> > +			list_for_each_entry(cl, &component->children, node) {
> > +				if (!alloc_new_node(cl, &info->vbt_list))
> > +					goto bail;
> > +			}
> > +		} else {
> > +			DRM_DEBUG_DRIVER("i915/config: Unknown component : %s\n", cname);
> >  		}
> >  	}
> >  
> > @@ -284,6 +298,8 @@ bail:
> >  		kfree(new_node);
> >  	list_for_each_entry_safe(new_node, tmp, &info->wa_list, node)
> >  		kfree(new_node);
> > +	list_for_each_entry_safe(new_node, tmp, &info->vbt_list, node)
> > +		kfree(new_node);
> >  
> >  	kfree(info);
> >  	dev_priv->config_info = NULL;
> > @@ -318,6 +334,8 @@ void intel_config_shutdown(struct drm_device *dev)
> >  		kfree(n);
> >  	list_for_each_entry_safe(n, tmp, &info->wa_list, node)
> >  		kfree(n);
> > +	list_for_each_entry_safe(n, tmp, &info->vbt_list, node)
> > +		kfree(n);
> >  
> >  	/* Unload any dynamically loaded ACPI property table */
> >  	handle = ACPI_HANDLE(dev->dev);
> > @@ -395,6 +413,8 @@ static struct list_head *cfg_type_to_list(struct intel_config_info *info,
> >  		return &info->plane_list;
> >  	case CFG_WORKAROUND:
> >  		return &info->wa_list;
> > +	case CFG_VBT:
> > +		return &info->vbt_list;
> >  	}
> >  	return NULL;
> >  }
> > @@ -433,6 +453,320 @@ bool intel_config_get_integer(struct drm_i915_private *dev_priv,
> >  	return false;
> >  }
> >  
> > +static void parse_port_info(struct drm_i915_private *dev_priv,
> > +			    const union acpi_object *pkg,
> > +			    int port)
> > +{
> > +	u32 supports;
> > +
> > +	if (pkg->type != ACPI_TYPE_PACKAGE)
> > +		return;
> > +
> > +	dev_priv->vbt.ddi_port_info[port].hdmi_level_shift =
> > +		(u32)pkg->package.elements[0].integer.value;
> > +
> > +	supports = (u32)pkg->package.elements[1].integer.value;
> > +	dev_priv->vbt.ddi_port_info[port].supports_dvi  = supports & 0x01;
> > +	dev_priv->vbt.ddi_port_info[port].supports_hdmi = supports & 0x02;
> > +	dev_priv->vbt.ddi_port_info[port].supports_dp   = supports & 0x04;
> > +}
> > +
> > +static struct drm_display_mode *parse_mode_info(const union acpi_object *pkg)
> > +{
> > +	struct drm_display_mode *mode;
> > +
> > +	if (pkg->type != ACPI_TYPE_PACKAGE)
> > +		return NULL;
> > +
> > +	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
> > +	if (!mode || pkg->package.count != 10)
> > +		return NULL;
> > +
> > +	mode->hdisplay = (u32)pkg->package.elements[0].integer.value;
> > +	mode->hsync_start = (u32)pkg->package.elements[1].integer.value;
> > +	mode->hsync_end = (u32)pkg->package.elements[3].integer.value;
> > +	mode->htotal = (u32)pkg->package.elements[3].integer.value;
> > +	mode->vdisplay = (u32)pkg->package.elements[4].integer.value;
> > +	mode->vsync_start = (u32)pkg->package.elements[5].integer.value;
> > +	mode->vsync_end = (u32)pkg->package.elements[6].integer.value;
> > +	mode->vtotal = (u32)pkg->package.elements[7].integer.value;
> > +	mode->clock = (u32)pkg->package.elements[8].integer.value;
> > +	mode->flags = (u32)pkg->package.elements[9].integer.value;
> > +	mode->type = DRM_MODE_TYPE_PREFERRED;
> > +
> > +	return mode;
> > +}
> > +
> > +
> > +#define PROPERTY_MATCH(prop, name)\
> > +	(strcasecmp(prop->string.pointer, name) == 0)
> > +
> > +/*
> > + * Set any general vbt features defined in the ACPI table.
> > + */
> > +static void parse_vbt_general(struct drm_i915_private *dev_priv,
> > +			      const union acpi_object *properties,
> > +			      struct acpi_device *adev)
> > +{
> > +	const union acpi_object *prop, *name, *value;
> > +	int i;
> > +
> > +	for (i = 0; i < properties->package.count; i++) {
> > +		prop = &properties->package.elements[i];
> > +		name = &prop->package.elements[0];
> > +		value = &prop->package.elements[1];
> > +
> > +		if (PROPERTY_MATCH(name, "Internal TV"))
> > +			dev_priv->vbt.int_tv_support =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "Internal CRT"))
> > +			dev_priv->vbt.int_crt_support =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "port info A"))
> > +			parse_port_info(dev_priv, value, PORT_A);
> > +		else if (PROPERTY_MATCH(name, "port info B"))
> > +			parse_port_info(dev_priv, value, PORT_B);
> > +		else if (PROPERTY_MATCH(name, "port info C"))
> > +			parse_port_info(dev_priv, value, PORT_C);
> > +		else if (PROPERTY_MATCH(name, "port info D"))
> > +			parse_port_info(dev_priv, value, PORT_D);
> > +		else if (PROPERTY_MATCH(name, "port info E"))
> > +			parse_port_info(dev_priv, value, PORT_E);
> > +		else if (PROPERTY_MATCH(name, "crt ddc pin"))
> > +			dev_priv->vbt.crt_ddc_pin = (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "drrs type"))
> > +			dev_priv->vbt.drrs_type = (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "fdi rx polarity inverted"))
> > +			dev_priv->vbt.fdi_rx_polarity_inverted =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "display clock mode"))
> > +			dev_priv->vbt.display_clock_mode =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "mode"))
> > +			dev_priv->vbt.lfp_lvds_vbt_mode =
> > +			    parse_mode_info(value);
> > +	}
> > +}
> > +
> > +static void parse_vbt_lvds(struct drm_i915_private *dev_priv,
> > +			   const union acpi_object *properties,
> > +			   struct acpi_device *adev)
> > +{
> > +	const union acpi_object *prop, *name, *value;
> > +	int i;
> > +
> > +	for (i = 0; i < properties->package.count; i++) {
> > +		prop = &properties->package.elements[i];
> > +		name = &prop->package.elements[0];
> > +		value = &prop->package.elements[1];
> > +
> > +		if (PROPERTY_MATCH(name, "lvds use ssc"))
> > +			dev_priv->vbt.lvds_use_ssc = (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "LVDS SSC Freq"))
> > +			dev_priv->vbt.lvds_ssc_freq =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "lvds downclock avail"))
> > +			dev_priv->lvds_downclock_avail =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "lvds downclock"))
> > +			dev_priv->lvds_downclock = (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "Pixel Dither"))
> > +			dev_priv->vbt.lvds_dither = (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "bios lvds val"))
> > +			dev_priv->vbt.bios_lvds_val =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "lvds vbt"))
> > +			dev_priv->vbt.lvds_vbt = (u32)value->integer.value;
> > +	}
> > +}
> > +
> > +static void parse_pwsq(struct drm_i915_private *dev_priv,
> > +		       const union acpi_object *properties)
> > +{
> > +	const union acpi_object *prop, *name, *value;
> > +	int i;
> > +
> > +	for (i = 0; i < properties->package.count; i++) {
> > +		prop = &properties->package.elements[i];
> > +		name = &prop->package.elements[0];
> > +		value = &prop->package.elements[1];
> > +
> > +		if (PROPERTY_MATCH(name, "t1/t3"))
> > +			dev_priv->vbt.edp_pps.t1_t3 =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "t8"))
> > +			dev_priv->vbt.edp_pps.t8 = (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "t9"))
> > +			dev_priv->vbt.edp_pps.t9 = (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "t10"))
> > +			dev_priv->vbt.edp_pps.t10 = (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "t11/t12"))
> > +			dev_priv->vbt.edp_pps.t11_t12 =
> > +			    (u32)value->integer.value;
> > +	}
> > +}
> > +
> > +static void parse_backlight(struct drm_i915_private *dev_priv,
> > +			    const union acpi_object *properties)
> > +{
> > +	const union acpi_object *prop, *name, *value;
> > +	int i;
> > +
> > +	for (i = 0; i < properties->package.count; i++) {
> > +		prop = &properties->package.elements[i];
> > +		name = &prop->package.elements[0];
> > +		value = &prop->package.elements[1];
> > +
> > +		if (PROPERTY_MATCH(name, "present"))
> > +			dev_priv->vbt.backlight.present =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "pwm freq hz"))
> > +			dev_priv->vbt.backlight.pwm_freq_hz =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "active low pwm"))
> > +			dev_priv->vbt.backlight.active_low_pwm =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "min brightness"))
> > +			dev_priv->vbt.backlight.min_brightness =
> > +			    (u32)value->integer.value;
> > +	}
> > +}
> > +
> > +static void parse_psr(struct drm_i915_private *dev_priv,
> > +		      const union acpi_object *properties)
> > +{
> > +	const union acpi_object *prop, *name, *value;
> > +	int i;
> > +
> > +	for (i = 0; i < properties->package.count; i++) {
> > +		prop = &properties->package.elements[i];
> > +		name = &prop->package.elements[0];
> > +		value = &prop->package.elements[1];
> > +
> > +		if (PROPERTY_MATCH(name, "full link"))
> > +			dev_priv->vbt.psr.full_link =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "require aux wakeup"))
> > +			dev_priv->vbt.psr.require_aux_wakeup =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "idle frames"))
> > +			dev_priv->vbt.psr.idle_frames =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "lines to wait"))
> > +			dev_priv->vbt.psr.lines_to_wait =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "tp1 wakeup time"))
> > +			dev_priv->vbt.psr.tp1_wakeup_time =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "tp2 tp3 wakeup time"))
> > +			dev_priv->vbt.psr.tp2_tp3_wakeup_time =
> > +			    (u32)value->integer.value;
> > +	}
> > +}
> > +
> > +static void parse_vbt_edp(struct drm_i915_private *dev_priv,
> > +			  const union acpi_object *properties,
> > +			  struct acpi_device *adev)
> > +{
> > +	const union acpi_object *prop, *name, *value;
> > +	int i;
> > +	struct acpi_device *component;
> > +
> > +	/* Child devices for Power sequencing, PSR and Backlight */
> > +	list_for_each_entry(component, &adev->children, node) {
> > +		char *sub_section_name;
> > +		const union acpi_object *properties;
> > +
> > +		if (!component)
> > +			continue;
> > +
> > +		sub_section_name = acpi_device_bid(component);
> > +		properties = component->data.properties;
> > +
> > +		if (!properties)
> > +			continue;
> > +
> > +		if (strcmp(sub_section_name, "PWSQ") == 0)
> > +			parse_pwsq(dev_priv, properties);
> > +		else if (strcmp(sub_section_name, "BLKT") == 0)
> > +			parse_backlight(dev_priv, properties);
> > +		else if (strcmp(sub_section_name, "PSR") == 0)
> > +			parse_psr(dev_priv, properties);
> > +	}
> > +
> > +	/* Process any EDP port configuration  */
> > +	for (i = 0; i < properties->package.count; i++) {
> > +		prop = &properties->package.elements[i];
> > +		name = &prop->package.elements[0];
> > +		value = &prop->package.elements[1];
> > +
> > +		if (PROPERTY_MATCH(name, "edp bpp"))
> > +			dev_priv->vbt.edp_bpp = (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "edp pps")) {
> > +			/*
> > +			 * The power sequence timing values are stored in
> > +			 * an array
> > +			 */
> > +			dev_priv->vbt.edp_pps.t1_t3 =
> > +				(u32)value->package.elements[0].integer.value;
> > +			dev_priv->vbt.edp_pps.t8 =
> > +				(u32)value->package.elements[1].integer.value;
> > +			dev_priv->vbt.edp_pps.t9 =
> > +				(u32)value->package.elements[2].integer.value;
> > +			dev_priv->vbt.edp_pps.t10 =
> > +				(u32)value->package.elements[3].integer.value;
> > +			dev_priv->vbt.edp_pps.t11_t12 =
> > +				(u32)value->package.elements[4].integer.value;
> > +		} else if (PROPERTY_MATCH(name, "edp rate"))
> > +			dev_priv->vbt.edp_rate = (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "edp lanes"))
> > +			dev_priv->vbt.edp_lanes = (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "edp preemphasis"))
> > +			dev_priv->vbt.edp_preemphasis =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "edp vswing"))
> > +			dev_priv->vbt.edp_vswing = (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "edp initialized"))
> > +			dev_priv->vbt.edp_initialized =
> > +			    (u32)value->integer.value;
> > +		else if (PROPERTY_MATCH(name, "edp support"))
> > +			dev_priv->vbt.edp_support = (u32)value->integer.value;
> > +	}
> > +}
> > +
> > +/*
> > + * Port device configration based on VBT.
> > + *
> > + * Use the configuration information to overwrite any
> > + * corresponding VBT values or provide initial configuration
> > + * if VBT doens't exist.
> > + */
> > +void intel_config_vbt(struct drm_i915_private *dev_priv)
> > +{
> > +	struct intel_config_info *info = dev_priv->config_info;
> > +	const union acpi_object *properties;
> > +	struct list_head *list;
> > +	struct intel_config_node *n;
> > +	char *sub_section_name;
> > +
> > +	list = cfg_type_to_list(info, CFG_VBT);
> > +	list_for_each_entry(n, list, node) {
> > +		sub_section_name = acpi_device_bid(n->adev);
> > +		properties = n->adev->data.properties;
> > +		if (!properties)
> > +			continue;
> > +
> > +		/* Call into sub section handlers */
> > +		if (strcmp(sub_section_name, "VBT") == 0)
> > +			parse_vbt_general(dev_priv, properties, n->adev);
> > +		else if (strcmp(sub_section_name, "LVDS") == 0)
> > +			parse_vbt_lvds(dev_priv, properties, n->adev);
> > +		else if (strcmp(sub_section_name, "EDP") == 0)
> > +			parse_vbt_edp(dev_priv, properties, n->adev);
> > +		else if (strcmp(sub_section_name, "DSI") == 0)
> > +			DRM_DEBUG_DRIVER("i915/config/vbt: Process Mipi DSI VBT features\n");
> > +	}
> > +}
> >  
> >  /*
> >   * Use ACPI methods to enumerate the items in the WA list.
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index e2b4e09..cc5da99 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1266,12 +1266,14 @@ enum cfg_type {
> >  	CFG_CRTC,
> >  	CFG_CONNECTOR,
> >  	CFG_PLANE,
> > -	CFG_WORKAROUND
> > +	CFG_WORKAROUND,
> > +	CFG_VBT
> >  };
> >  
> >  void intel_config_init(struct drm_device *dev);
> >  void intel_config_shutdown(struct drm_device *dev);
> >  bool intel_config_wa_add(struct drm_i915_private *dev_priv);
> > +void intel_config_vbt(struct drm_i915_private *dev_priv);
> >  bool intel_config_get_integer(struct drm_i915_private *dev_priv,
> >  			  enum cfg_type cfg_type,
> >  			  const char *name,
> > -- 
> > 2.1.0
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 01/12] drm/i915/config: Initial framework
  2015-02-24 17:41     ` Bob Paauwe
@ 2015-02-24 20:47       ` Daniel Vetter
  0 siblings, 0 replies; 32+ messages in thread
From: Daniel Vetter @ 2015-02-24 20:47 UTC (permalink / raw)
  To: Bob Paauwe; +Cc: intel-gfx

On Tue, Feb 24, 2015 at 09:41:41AM -0800, Bob Paauwe wrote:
> On Tue, 24 Feb 2015 17:17:18 +0100
> Daniel Vetter <daniel@ffwll.ch> wrote:
> > 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. 

Yeah I don't expect anyone else but i915 to use this, but reusing the
atomic interface (which is already abi towards userspace) means we don't
have another slightly different interface where abi compatibility matters.
Hence why I want to reuse the atomic interface.

ARM ofc has the cross-vendor dt, so there even code reuse would be
possible. And there's still rumours that at least some arm64 platforms
will only ship with acpi, so maybe there's even some room to share that
code. But really my main goal is to not create another ABI layer but
instead try to fully reuse the atomic one by using a mechanical mapping
for acpi.

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

Well I haven't looked at it in details. And I dont think anyone but your
group has a need for this, so not sure who could do a more in-depth review
if you want that.

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 09/12] drm/i915/config: Add VBT settings configuration.
  2015-02-24 18:37     ` Bob Paauwe
@ 2015-02-24 20:52       ` Daniel Vetter
  2015-02-24 22:23         ` Bob Paauwe
  2015-05-15  9:39         ` Ville Syrjälä
  0 siblings, 2 replies; 32+ messages in thread
From: Daniel Vetter @ 2015-02-24 20:52 UTC (permalink / raw)
  To: Bob Paauwe; +Cc: intel-gfx

On Tue, Feb 24, 2015 at 10:37:10AM -0800, Bob Paauwe wrote:
> On Tue, 24 Feb 2015 14:57:48 +0100
> Daniel Vetter <daniel@ffwll.ch> wrote:
> > As Jani points out we already have vbt headaches, it would be good if we
> > only have those once ;-)
> > -Daniel
> 
> I've been trying to think of a better way but not really coming up with
> something that scales well. EMGD took the approach of create
> configuration for only those values that we had customer requests for.
> And that was primarily just the panel power up/down timing sequence and
> some backlight control. We never tried to replicate everything that
> could be set via vbt.

If it's only a very few select things we could just add them as atomic
properties to connectors. No need for anything special, and we could even
use that to debug panel issues at runtime.

We need a lot of the dp things already anyway for the dp validation stuff,
but since that was debug Dave shot down my idea to just go with props. But
here we have another user, and this one will have full abi compat
requirements. So no longer any reasons to not go with props imo.

Or else we just smash an entire vbt into acpi, for my that's ok (we need
to deal with vbt anyway).
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 09/12] drm/i915/config: Add VBT settings configuration.
  2015-02-24 20:52       ` Daniel Vetter
@ 2015-02-24 22:23         ` Bob Paauwe
  2015-05-15  9:39         ` Ville Syrjälä
  1 sibling, 0 replies; 32+ messages in thread
From: Bob Paauwe @ 2015-02-24 22:23 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Tue, 24 Feb 2015 21:52:16 +0100
Daniel Vetter <daniel@ffwll.ch> wrote:

> On Tue, Feb 24, 2015 at 10:37:10AM -0800, Bob Paauwe wrote:
> > On Tue, 24 Feb 2015 14:57:48 +0100
> > Daniel Vetter <daniel@ffwll.ch> wrote:
> > > As Jani points out we already have vbt headaches, it would be good if we
> > > only have those once ;-)
> > > -Daniel
> > 
> > I've been trying to think of a better way but not really coming up with
> > something that scales well. EMGD took the approach of create
> > configuration for only those values that we had customer requests for.
> > And that was primarily just the panel power up/down timing sequence and
> > some backlight control. We never tried to replicate everything that
> > could be set via vbt.
> 
> If it's only a very few select things we could just add them as atomic
> properties to connectors. No need for anything special, and we could even
> use that to debug panel issues at runtime.
> 
> We need a lot of the dp things already anyway for the dp validation stuff,
> but since that was debug Dave shot down my idea to just go with props. But
> here we have another user, and this one will have full abi compat
> requirements. So no longer any reasons to not go with props imo.
> 
> Or else we just smash an entire vbt into acpi, for my that's ok (we need
> to deal with vbt anyway).
> -Daniel


Funny... As I was looking at the atomic code I had the same thought to
use atomic properties but dismissed it because I thought it would be
too much overhead to do that for all of the vbt flags/values.   But it
it's limited, at least initially, to what we know we need that would
work and this whole bit magically goes away.

Thanks! Looks like it's time for me to really start digging into atomic.

Bob
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 09/12] drm/i915/config: Add VBT settings configuration.
  2015-02-24 20:52       ` Daniel Vetter
  2015-02-24 22:23         ` Bob Paauwe
@ 2015-05-15  9:39         ` Ville Syrjälä
  2015-05-20 17:07           ` Bob Paauwe
  1 sibling, 1 reply; 32+ messages in thread
From: Ville Syrjälä @ 2015-05-15  9:39 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Tue, Feb 24, 2015 at 09:52:16PM +0100, Daniel Vetter wrote:
> On Tue, Feb 24, 2015 at 10:37:10AM -0800, Bob Paauwe wrote:
> > On Tue, 24 Feb 2015 14:57:48 +0100
> > Daniel Vetter <daniel@ffwll.ch> wrote:
> > > As Jani points out we already have vbt headaches, it would be good if we
> > > only have those once ;-)
> > > -Daniel
> > 
> > I've been trying to think of a better way but not really coming up with
> > something that scales well. EMGD took the approach of create
> > configuration for only those values that we had customer requests for.
> > And that was primarily just the panel power up/down timing sequence and
> > some backlight control. We never tried to replicate everything that
> > could be set via vbt.
> 
> If it's only a very few select things we could just add them as atomic
> properties to connectors. No need for anything special, and we could even
> use that to debug panel issues at runtime.

I think properties should only be used for something that the user
might actually want to configure. Not sure what exactly we're talking
about here, but eg. panel timings are definitely not in that category
IMO.

> 
> We need a lot of the dp things already anyway for the dp validation stuff,
> but since that was debug Dave shot down my idea to just go with props. But
> here we have another user, and this one will have full abi compat
> requirements. So no longer any reasons to not go with props imo.
> 
> Or else we just smash an entire vbt into acpi, for my that's ok (we need
> to deal with vbt anyway).
> -Daniel
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 09/12] drm/i915/config: Add VBT settings configuration.
  2015-05-15  9:39         ` Ville Syrjälä
@ 2015-05-20 17:07           ` Bob Paauwe
  2015-05-21  8:37             ` Daniel Vetter
  0 siblings, 1 reply; 32+ messages in thread
From: Bob Paauwe @ 2015-05-20 17:07 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Fri, 15 May 2015 12:39:20 +0300
Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:

> On Tue, Feb 24, 2015 at 09:52:16PM +0100, Daniel Vetter wrote:
> > On Tue, Feb 24, 2015 at 10:37:10AM -0800, Bob Paauwe wrote:
> > > On Tue, 24 Feb 2015 14:57:48 +0100
> > > Daniel Vetter <daniel@ffwll.ch> wrote:
> > > > As Jani points out we already have vbt headaches, it would be good if we
> > > > only have those once ;-)
> > > > -Daniel
> > > 
> > > I've been trying to think of a better way but not really coming up with
> > > something that scales well. EMGD took the approach of create
> > > configuration for only those values that we had customer requests for.
> > > And that was primarily just the panel power up/down timing sequence and
> > > some backlight control. We never tried to replicate everything that
> > > could be set via vbt.
> > 
> > If it's only a very few select things we could just add them as atomic
> > properties to connectors. No need for anything special, and we could even
> > use that to debug panel issues at runtime.
> 
> I think properties should only be used for something that the user
> might actually want to configure. Not sure what exactly we're talking
> about here, but eg. panel timings are definitely not in that category
> IMO.
> 
I did create an implementation that used properties for this (and a
couple of other things) and that was my conclusion as well. These would
probably have to be read-only properties with the values set by some
configuration framework (like the ACPI property framework this was
originally part of).

I also did an implementation where I set these via module parameters
and, to me, that seems more reasonable. It's easy to implement and a
fairly simple patch to maintain. 

Given the small number of items that EMGD can currently configure at
driver load that i915 can't, I'm really questioning the need for a
full configuration framework.  I'm also trying to determine if we even
have requirements for these anymore or if they were added in to EMGD at
some point to workaround broken firmware.  If we do end up with a
customer requirement to configure the panel power sequence, maintaining
an embedded only patch to add module parameters may suffice.

The two other items that EMGD has currently are backlight related (max
and level) and DPCD max link rate. I'm also trying to determine if
there's really a requirement for overriding these. If there is, module
parameters would be the easiest way here too.

When I started looking at configuration at driver load I thought we
had a lot of different things that needed to be configured, which is
why I discounted using module parameters and was looking at a larger
framework solution.  Another consideration that has come into play is
that a framework solution, like the ACPI one that I posted, has
negative impact on driver load time. And driver load time is
very important to some customers. 

> > 
> > We need a lot of the dp things already anyway for the dp validation stuff,
> > but since that was debug Dave shot down my idea to just go with props. But
> > here we have another user, and this one will have full abi compat
> > requirements. So no longer any reasons to not go with props imo.
> > 
> > Or else we just smash an entire vbt into acpi, for my that's ok (we need
> > to deal with vbt anyway).
> > -Daniel
> > -- 
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > +41 (0) 79 365 57 48 - http://blog.ffwll.ch
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 09/12] drm/i915/config: Add VBT settings configuration.
  2015-05-20 17:07           ` Bob Paauwe
@ 2015-05-21  8:37             ` Daniel Vetter
  2015-05-26 21:20               ` Bob Paauwe
  0 siblings, 1 reply; 32+ messages in thread
From: Daniel Vetter @ 2015-05-21  8:37 UTC (permalink / raw)
  To: Bob Paauwe; +Cc: intel-gfx

On Wed, May 20, 2015 at 10:07:58AM -0700, Bob Paauwe wrote:
> On Fri, 15 May 2015 12:39:20 +0300
> Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> 
> > On Tue, Feb 24, 2015 at 09:52:16PM +0100, Daniel Vetter wrote:
> > > On Tue, Feb 24, 2015 at 10:37:10AM -0800, Bob Paauwe wrote:
> > > > On Tue, 24 Feb 2015 14:57:48 +0100
> > > > Daniel Vetter <daniel@ffwll.ch> wrote:
> > > > > As Jani points out we already have vbt headaches, it would be good if we
> > > > > only have those once ;-)
> > > > > -Daniel
> > > > 
> > > > I've been trying to think of a better way but not really coming up with
> > > > something that scales well. EMGD took the approach of create
> > > > configuration for only those values that we had customer requests for.
> > > > And that was primarily just the panel power up/down timing sequence and
> > > > some backlight control. We never tried to replicate everything that
> > > > could be set via vbt.
> > > 
> > > If it's only a very few select things we could just add them as atomic
> > > properties to connectors. No need for anything special, and we could even
> > > use that to debug panel issues at runtime.
> > 
> > I think properties should only be used for something that the user
> > might actually want to configure. Not sure what exactly we're talking
> > about here, but eg. panel timings are definitely not in that category
> > IMO.
> > 
> I did create an implementation that used properties for this (and a
> couple of other things) and that was my conclusion as well. These would
> probably have to be read-only properties with the values set by some
> configuration framework (like the ACPI property framework this was
> originally part of).
> 
> I also did an implementation where I set these via module parameters
> and, to me, that seems more reasonable. It's easy to implement and a
> fairly simple patch to maintain. 
> 
> Given the small number of items that EMGD can currently configure at
> driver load that i915 can't, I'm really questioning the need for a
> full configuration framework.  I'm also trying to determine if we even
> have requirements for these anymore or if they were added in to EMGD at
> some point to workaround broken firmware.  If we do end up with a
> customer requirement to configure the panel power sequence, maintaining
> an embedded only patch to add module parameters may suffice.
> 
> The two other items that EMGD has currently are backlight related (max
> and level) and DPCD max link rate. I'm also trying to determine if
> there's really a requirement for overriding these. If there is, module
> parameters would be the easiest way here too.
> 
> When I started looking at configuration at driver load I thought we
> had a lot of different things that needed to be configured, which is
> why I discounted using module parameters and was looking at a larger
> framework solution.  Another consideration that has come into play is
> that a framework solution, like the ACPI one that I posted, has
> negative impact on driver load time. And driver load time is
> very important to some customers. 

For me the big reason for an entire framework was that we also wanted to
spec the initial modeset, including any kind of splash screen loaded as
firmware blobs. That's also the reason for aiming for properties by
default (that's the new transport for all things modeset after all), and
using hidden configuration variables only for cases where a prop really
doesn't make any sense.

But if that initial modeset use-cases is nuked too I agreee there's indeed
not much left to justify an entire framework ...
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 09/12] drm/i915/config: Add VBT settings configuration.
  2015-05-21  8:37             ` Daniel Vetter
@ 2015-05-26 21:20               ` Bob Paauwe
  2015-05-27 12:23                 ` Daniel Vetter
  0 siblings, 1 reply; 32+ messages in thread
From: Bob Paauwe @ 2015-05-26 21:20 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Thu, 21 May 2015 10:37:07 +0200
Daniel Vetter <daniel@ffwll.ch> wrote:

> On Wed, May 20, 2015 at 10:07:58AM -0700, Bob Paauwe wrote:
> > On Fri, 15 May 2015 12:39:20 +0300
> > Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> > 
> > > On Tue, Feb 24, 2015 at 09:52:16PM +0100, Daniel Vetter wrote:
> > > > On Tue, Feb 24, 2015 at 10:37:10AM -0800, Bob Paauwe wrote:
> > > > > On Tue, 24 Feb 2015 14:57:48 +0100
> > > > > Daniel Vetter <daniel@ffwll.ch> wrote:
> > > > > > As Jani points out we already have vbt headaches, it would be good if we
> > > > > > only have those once ;-)
> > > > > > -Daniel
> > > > > 
> > > > > I've been trying to think of a better way but not really coming up with
> > > > > something that scales well. EMGD took the approach of create
> > > > > configuration for only those values that we had customer requests for.
> > > > > And that was primarily just the panel power up/down timing sequence and
> > > > > some backlight control. We never tried to replicate everything that
> > > > > could be set via vbt.
> > > > 
> > > > If it's only a very few select things we could just add them as atomic
> > > > properties to connectors. No need for anything special, and we could even
> > > > use that to debug panel issues at runtime.
> > > 
> > > I think properties should only be used for something that the user
> > > might actually want to configure. Not sure what exactly we're talking
> > > about here, but eg. panel timings are definitely not in that category
> > > IMO.
> > > 
> > I did create an implementation that used properties for this (and a
> > couple of other things) and that was my conclusion as well. These would
> > probably have to be read-only properties with the values set by some
> > configuration framework (like the ACPI property framework this was
> > originally part of).
> > 
> > I also did an implementation where I set these via module parameters
> > and, to me, that seems more reasonable. It's easy to implement and a
> > fairly simple patch to maintain. 
> > 
> > Given the small number of items that EMGD can currently configure at
> > driver load that i915 can't, I'm really questioning the need for a
> > full configuration framework.  I'm also trying to determine if we even
> > have requirements for these anymore or if they were added in to EMGD at
> > some point to workaround broken firmware.  If we do end up with a
> > customer requirement to configure the panel power sequence, maintaining
> > an embedded only patch to add module parameters may suffice.
> > 
> > The two other items that EMGD has currently are backlight related (max
> > and level) and DPCD max link rate. I'm also trying to determine if
> > there's really a requirement for overriding these. If there is, module
> > parameters would be the easiest way here too.
> > 
> > When I started looking at configuration at driver load I thought we
> > had a lot of different things that needed to be configured, which is
> > why I discounted using module parameters and was looking at a larger
> > framework solution.  Another consideration that has come into play is
> > that a framework solution, like the ACPI one that I posted, has
> > negative impact on driver load time. And driver load time is
> > very important to some customers. 
> 
> For me the big reason for an entire framework was that we also wanted to
> spec the initial modeset, including any kind of splash screen loaded as
> firmware blobs. That's also the reason for aiming for properties by
> default (that's the new transport for all things modeset after all), and
> using hidden configuration variables only for cases where a prop really
> doesn't make any sense.
> 
> But if that initial modeset use-cases is nuked too I agreee there's indeed
> not much left to justify an entire framework ...
> -Daniel

The initial mode set use-case isn't nuked but that use-case exist
to try and parallelize the mode in the kernel boot phase as a way to
reduce time to first flip.  Right now, the ACPI functions add enough
overhead that I'm concerned it will negate the advantage of doing the
initial mode set in the driver.

With the framework, read-only properties is compelling. I'm
experimenting with an number of different implementations and trying to
get feedback on all of them.  Nothing yet has jumped out as the perfect
implementation.

This is mostly back-burned right now as I wait for all the atomic
mode setting code to land.
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [RFC 09/12] drm/i915/config: Add VBT settings configuration.
  2015-05-26 21:20               ` Bob Paauwe
@ 2015-05-27 12:23                 ` Daniel Vetter
  0 siblings, 0 replies; 32+ messages in thread
From: Daniel Vetter @ 2015-05-27 12:23 UTC (permalink / raw)
  To: Bob Paauwe; +Cc: intel-gfx

On Tue, May 26, 2015 at 02:20:00PM -0700, Bob Paauwe wrote:
> On Thu, 21 May 2015 10:37:07 +0200
> Daniel Vetter <daniel@ffwll.ch> wrote:
> 
> > On Wed, May 20, 2015 at 10:07:58AM -0700, Bob Paauwe wrote:
> > > On Fri, 15 May 2015 12:39:20 +0300
> > > Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> > > 
> > > > On Tue, Feb 24, 2015 at 09:52:16PM +0100, Daniel Vetter wrote:
> > > > > On Tue, Feb 24, 2015 at 10:37:10AM -0800, Bob Paauwe wrote:
> > > > > > On Tue, 24 Feb 2015 14:57:48 +0100
> > > > > > Daniel Vetter <daniel@ffwll.ch> wrote:
> > > > > > > As Jani points out we already have vbt headaches, it would be good if we
> > > > > > > only have those once ;-)
> > > > > > > -Daniel
> > > > > > 
> > > > > > I've been trying to think of a better way but not really coming up with
> > > > > > something that scales well. EMGD took the approach of create
> > > > > > configuration for only those values that we had customer requests for.
> > > > > > And that was primarily just the panel power up/down timing sequence and
> > > > > > some backlight control. We never tried to replicate everything that
> > > > > > could be set via vbt.
> > > > > 
> > > > > If it's only a very few select things we could just add them as atomic
> > > > > properties to connectors. No need for anything special, and we could even
> > > > > use that to debug panel issues at runtime.
> > > > 
> > > > I think properties should only be used for something that the user
> > > > might actually want to configure. Not sure what exactly we're talking
> > > > about here, but eg. panel timings are definitely not in that category
> > > > IMO.
> > > > 
> > > I did create an implementation that used properties for this (and a
> > > couple of other things) and that was my conclusion as well. These would
> > > probably have to be read-only properties with the values set by some
> > > configuration framework (like the ACPI property framework this was
> > > originally part of).
> > > 
> > > I also did an implementation where I set these via module parameters
> > > and, to me, that seems more reasonable. It's easy to implement and a
> > > fairly simple patch to maintain. 
> > > 
> > > Given the small number of items that EMGD can currently configure at
> > > driver load that i915 can't, I'm really questioning the need for a
> > > full configuration framework.  I'm also trying to determine if we even
> > > have requirements for these anymore or if they were added in to EMGD at
> > > some point to workaround broken firmware.  If we do end up with a
> > > customer requirement to configure the panel power sequence, maintaining
> > > an embedded only patch to add module parameters may suffice.
> > > 
> > > The two other items that EMGD has currently are backlight related (max
> > > and level) and DPCD max link rate. I'm also trying to determine if
> > > there's really a requirement for overriding these. If there is, module
> > > parameters would be the easiest way here too.
> > > 
> > > When I started looking at configuration at driver load I thought we
> > > had a lot of different things that needed to be configured, which is
> > > why I discounted using module parameters and was looking at a larger
> > > framework solution.  Another consideration that has come into play is
> > > that a framework solution, like the ACPI one that I posted, has
> > > negative impact on driver load time. And driver load time is
> > > very important to some customers. 
> > 
> > For me the big reason for an entire framework was that we also wanted to
> > spec the initial modeset, including any kind of splash screen loaded as
> > firmware blobs. That's also the reason for aiming for properties by
> > default (that's the new transport for all things modeset after all), and
> > using hidden configuration variables only for cases where a prop really
> > doesn't make any sense.
> > 
> > But if that initial modeset use-cases is nuked too I agreee there's indeed
> > not much left to justify an entire framework ...
> > -Daniel
> 
> The initial mode set use-case isn't nuked but that use-case exist
> to try and parallelize the mode in the kernel boot phase as a way to
> reduce time to first flip.  Right now, the ACPI functions add enough
> overhead that I'm concerned it will negate the advantage of doing the
> initial mode set in the driver.
> 
> With the framework, read-only properties is compelling. I'm
> experimenting with an number of different implementations and trying to
> get feedback on all of them.  Nothing yet has jumped out as the perfect
> implementation.
> 
> This is mostly back-burned right now as I wait for all the atomic
> mode setting code to land.

Yeah that shiny new world of exposing everything modeset related in a
unified way as a property has unfortunately not yet materialized. Makes
sense to figure out first what we really need.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2015-05-27 12:21 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-12 23:41 [RFC 00/12] i915 init-time configuration Bob Paauwe
2015-02-12 23:41 ` [RFC 01/12] drm/i915/config: Initial framework Bob Paauwe
2015-02-13  8:19   ` Jani Nikula
2015-02-24 16:17   ` Daniel Vetter
2015-02-24 17:41     ` Bob Paauwe
2015-02-24 20:47       ` Daniel Vetter
2015-02-12 23:41 ` [RFC 02/12] drm/i915/config: Introduce intel_output_name Bob Paauwe
2015-02-13  8:12   ` Jani Nikula
2015-02-12 23:41 ` [RFC 03/12] drm/i915/config: Add init-time configuration of bits per color Bob Paauwe
2015-02-12 23:41 ` [RFC 04/12] drm/i915/config: Set dp panel fitter property based on init-time config Bob Paauwe
2015-02-12 23:41 ` [RFC 05/12] drm/i915/config: Set general connector properties using config Bob Paauwe
2015-02-12 23:41 ` [RFC 06/12] drm/i915/config: Split out allocation of list nodes Bob Paauwe
2015-02-13  8:15   ` Jani Nikula
2015-02-12 23:41 ` [RFC 07/12] drm/i915/config: Get workaround information from configuration Bob Paauwe
2015-02-24 13:51   ` Daniel Vetter
2015-02-24 17:54     ` Bob Paauwe
2015-02-12 23:41 ` [RFC 08/12] drm/i915/config: Use workarounds list " Bob Paauwe
2015-02-12 23:41 ` [RFC 09/12] drm/i915/config: Add VBT settings configuration Bob Paauwe
2015-02-24 13:57   ` Daniel Vetter
2015-02-24 18:37     ` Bob Paauwe
2015-02-24 20:52       ` Daniel Vetter
2015-02-24 22:23         ` Bob Paauwe
2015-05-15  9:39         ` Ville Syrjälä
2015-05-20 17:07           ` Bob Paauwe
2015-05-21  8:37             ` Daniel Vetter
2015-05-26 21:20               ` Bob Paauwe
2015-05-27 12:23                 ` Daniel Vetter
2015-02-12 23:41 ` [RFC 10/12] drm/i915/config: Introduce a test table and code to make use of it Bob Paauwe
2015-02-12 23:41 ` [RFC 11/12] drm/i915/config: Add workaround properties to ACPI table Bob Paauwe
2015-02-12 23:41 ` [RFC 12/12] drm/i915/config: Add ACPI device examples for VBT configuration Bob Paauwe
2015-02-13  8:08 ` [RFC 00/12] i915 init-time configuration Jani Nikula
2015-02-13 17:17   ` Bob Paauwe

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.