All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/8] Enable DC states for skl.
@ 2015-04-16  8:52 Animesh Manna
  2015-04-16  8:52 ` [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
                   ` (8 more replies)
  0 siblings, 9 replies; 37+ messages in thread
From: Animesh Manna @ 2015-04-16  8:52 UTC (permalink / raw)
  To: intel-gfx

v4:
- Removed all warning by reordering the patchsets.
- Changed the dmc firmware file name skl_dmc_ver1.bin, followed naming conventipon as <platform>_dmc_<api-version>.bin

v3:
MOdified the code of patch 1 and 3 based on review commets. 

v2:
Based on review comments modified the code.

v1:
Initial version send as RFC.

This patch series contains the implementation for enabling DC states for gen9 
platform, specifically for skl. Few bxt specific changes will be submitted 
separately in a different patch series which will be extended support for bxt 
and will use major portion of the code of this patch series.

A.Sunil Kamath (3):
  drm/i915/skl: Add support to load SKL CSR firmware.
  drm/i915/skl: Implement enable/disable for Display C5 state.
  Implement enable/disable for Display C6 state.

Suketu Shah (5):
  drm/i915/skl: Add DC5 Trigger Sequence.
  drm/i915/skl: Assert the requirements to enter or exit DC5.
  drm/i915/skl: Add DC6 Trigger sequence.
  drm/i915/skl: Assert the requirements to enter or exit DC6.
  drm/i915/skl: Enable runtime PM

 drivers/gpu/drm/i915/Makefile           |   3 +-
 drivers/gpu/drm/i915/i915_dma.c         |  11 +-
 drivers/gpu/drm/i915/i915_drv.c         |  50 ++++
 drivers/gpu/drm/i915/i915_drv.h         |  27 +-
 drivers/gpu/drm/i915/i915_reg.h         |  11 +
 drivers/gpu/drm/i915/intel_csr.c        | 421 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h        |   9 +
 drivers/gpu/drm/i915/intel_runtime_pm.c | 199 ++++++++++++++-
 8 files changed, 726 insertions(+), 5 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_csr.c

-- 
2.0.2

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

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

* [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware.
  2015-04-16  8:52 [PATCH v4 0/8] Enable DC states for skl Animesh Manna
@ 2015-04-16  8:52 ` Animesh Manna
  2015-04-16  9:18   ` Damien Lespiau
                     ` (2 more replies)
  2015-04-16  8:52 ` [PATCH v4 2/8] drm/i915/skl: Add DC5 Trigger Sequence Animesh Manna
                   ` (7 subsequent siblings)
  8 siblings, 3 replies; 37+ messages in thread
From: Animesh Manna @ 2015-04-16  8:52 UTC (permalink / raw)
  To: intel-gfx

From: "A.Sunil Kamath" <sunil.kamath@intel.com>

Display Context Save and Restore support is needed for
various SKL Display C states like DC5, DC6.

This implementation is added based on first version of DMC CSR program
that we received from h/w team.

Here we are using request_firmware based design.
Finally this firmware should end up in linux-firmware tree.

For SKL platform its mandatory to ensure that we load this
csr program before enabling DC states like DC5/DC6.

As CSR program gets reset on various conditions, we should ensure
to load it during boot and in future change to be added to load
this system resume sequence too.

v1: Initial relese as RFC patch

v2: Design change as per Daniel, Damien and Shobit's review comments
request firmware method followed.

v3: Some optimization and functional changes.
Pulled register defines into drivers/gpu/drm/i915/i915_reg.h
Used kmemdup to allocate and duplicate firmware content.
Ensured to free allocated buffer.

v4: Modified as per review comments from Satheesh and Daniel
Removed temporary buffer.
Optimized number of writes by replacing I915_WRITE with I915_WRITE64.

v5:
Modified as per review comemnts from Damien.
- Changed name for functions and firmware.
- Introduced HAS_CSR.
- Reverted back previous change and used csr_buf with u8 size.
- Using cpu_to_be64 for endianness change.

Modified as per review comments from Imre.
- Modified registers and macro names to be a bit closer to bspec terminology
and the existing register naming in the driver.
- Early return for non SKL platforms in intel_load_csr_program function.
- Added locking around CSR program load function as it may be called
concurrently during system/runtime resume.
- Releasing the fw before loading the program for consistency
- Handled error path during f/w load.

v6: Modified as per review comments from Imre.
- Corrected out_freecsr sequence.

v7: Modified as per review comments from Imre.
Fail loading fw if fw->size%8!=0.

v8: Rebase to latest.

v9: Rebase on top of -nightly (Damien)

v10: Enabled support for dmc firmware ver 1.0.
According to ver 1.0 in a single binary package all the firmware's that are
required for different stepping's of the product will be stored. The package
contains the css header, followed by the package header and the actual dmc
firmwares. Package header contains the firmware/stepping mapping table and
the corresponding firmware offsets to the individual binaries, within the
package. Each individual program binary contains the header and the payload
sections whose size is specified in the header section. This changes are done
to extract the specific firmaware from the package. (Animesh)

v11: Modified as per review comemnts from Imre.
- Added code comment from bpec for header structure elements.
- Added __packed to avoid structure padding.
- Added helper functions for stepping and substepping info.
- Added code comment for CSR_MAX_FW_SIZE.
- Disabled BXT firmware loading, will be enabled with dmc 1.0 support.
- Changed skl_stepping_info based on bspec, earlier used from config DB.
- Removed duplicate call of cpu_to_be* from intel_csr_load_program function.
- Used cpu_to_be32 instead of cpu_to_be64 as firmware binary in dword aligned.
- Added sanity check for header length.
- Added sanity check for mmio address got from firmware binary.
- kmalloc done separately for dmc header and dmc firmware. (Animesh)

v12: Modified as per review comemnts from Imre.
- Corrected the typo error in skl stepping info structure.
- Added out-of-bound access for skl_stepping_info.
- Sanity check for mmio address modified.
- Sanity check added for stepping and substeppig.
- Modified the intel_dmc_info structure, cache only the required header info. (Animesh)

v13: clarify firmware load error message.
The reason for a firmware loading failure can be obscure if the driver
is built-in. Provide an explanation to the user about the likely reason for
the failure and how to resolve it. (Imre)

v14: Suggested by Jani.
- fix s/I915/CONFIG_DRM_I915/ typo
- add fw_path to the firmware object instead of using a static ptr (Jani)

v15:
1) Changed the firmware name as dmc_gen9.bin, everytime for a new firmware version a symbolic link
with same name will help not to build kernel again.
2) Changes done as per review comments from Imre.
- Error check removed for intel_csr_ucode_init.
- Moved csr-specific data structure to intel_csr.h and optimization done on structure definition.
- fw->data used directly for parsing the header info & memory allocation
only done separately for payload. (Animesh)

v16:
- No need for out_regs label in i915_driver_load(), so removed it.
- Changed the firmware name as skl_dmc_ver1.bin, followed naming convention <platform>_dmc_<api-version>.bin (Animesh)

Issue: VIZ-2569
Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/Makefile    |   3 +-
 drivers/gpu/drm/i915/i915_dma.c  |  11 +-
 drivers/gpu/drm/i915/i915_drv.c  |  20 +++
 drivers/gpu/drm/i915/i915_drv.h  |  17 ++
 drivers/gpu/drm/i915/intel_csr.c | 367 +++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |   5 +
 6 files changed, 420 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_csr.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index a69002e..5238deb 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_csr.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 e44116f..a238889 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -816,6 +816,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	spin_lock_init(&dev_priv->mmio_flip_lock);
 	mutex_init(&dev_priv->dpio_lock);
 	mutex_init(&dev_priv->modeset_restore_lock);
+	mutex_init(&dev_priv->csr_lock);
 
 	intel_pm_setup(dev);
 
@@ -861,9 +862,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
 	intel_uncore_init(dev);
 
+	/* Load CSR Firmware for SKL */
+	intel_csr_ucode_init(dev);
+
 	ret = i915_gem_gtt_init(dev);
 	if (ret)
-		goto out_regs;
+		goto out_freecsr;
 
 	/* WARNING: Apparently we must kick fbdev drivers before vgacon,
 	 * otherwise the vga fbdev driver falls over. */
@@ -1033,7 +1037,8 @@ out_mtrrfree:
 	io_mapping_free(dev_priv->gtt.mappable);
 out_gtt:
 	i915_global_gtt_cleanup(dev);
-out_regs:
+out_freecsr:
+	intel_csr_ucode_fini(dev);
 	intel_uncore_fini(dev);
 	pci_iounmap(dev->pdev, dev_priv->regs);
 put_bridge:
@@ -1113,6 +1118,8 @@ int i915_driver_unload(struct drm_device *dev)
 	mutex_unlock(&dev->struct_mutex);
 	i915_gem_cleanup_stolen(dev);
 
+	intel_csr_ucode_fini(dev);
+
 	intel_teardown_gmbus(dev);
 	intel_teardown_mchbar(dev);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index c3fdbb0..acd0e2b 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -556,6 +556,26 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
 	cancel_delayed_work_sync(&dev_priv->hotplug_reenable_work);
 }
 
+void i915_firmware_load_error_print(const char *fw_path, int err)
+{
+	DRM_ERROR("failed to load firmware %s (%d)\n", fw_path, err);
+
+	/*
+	 * If the reason is not known assume -ENOENT since that's the most
+	 * usual failure mode.
+	 */
+	if (!err)
+		err = -ENOENT;
+
+	if (!(IS_BUILTIN(CONFIG_DRM_I915) && err == -ENOENT))
+		return;
+
+	DRM_ERROR(
+	  "The driver is built-in, so to load the firmware you need to\n"
+	  "include it either in the kernel (see CONFIG_EXTRA_FIRMWARE) or\n"
+	  "in your initrd/initramfs image.\n");
+}
+
 static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 47be4a5..90e47a9 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -667,6 +667,15 @@ struct intel_uncore {
 #define for_each_fw_domain(domain__, dev_priv__, i__) \
 	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
 
+struct intel_csr {
+	const char *fw_path;
+	__be32 *dmc_payload;
+	uint32_t dmc_fw_size;
+	uint32_t mmio_count;
+	uint32_t mmioaddr[8];
+	uint32_t mmiodata[8];
+};
+
 #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
 	func(is_mobile) sep \
 	func(is_i85x) sep \
@@ -1573,6 +1582,11 @@ struct drm_i915_private {
 
 	struct i915_virtual_gpu vgpu;
 
+	struct intel_csr csr;
+
+	/* Display CSR-related protection */
+	struct mutex csr_lock;
+
 	struct intel_gmbus gmbus[GMBUS_NUM_PINS];
 
 	/** gmbus_mutex protects against concurrent usage of the single hw gmbus
@@ -2425,6 +2439,8 @@ struct drm_i915_cmd_table {
 #define HAS_RC6(dev)		(INTEL_INFO(dev)->gen >= 6)
 #define HAS_RC6p(dev)		(INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
 
+#define HAS_CSR(dev)	(IS_SKYLAKE(dev))
+
 #define INTEL_PCH_DEVICE_ID_MASK		0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
 #define INTEL_PCH_CPT_DEVICE_ID_TYPE		0x1c00
@@ -2515,6 +2531,7 @@ extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
 extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
 int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
 void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
+void i915_firmware_load_error_print(const char *fw_path, int err);
 
 /* i915_irq.c */
 void i915_queue_hangcheck(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
new file mode 100644
index 0000000..f5fa574
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+#include <linux/firmware.h>
+#include "i915_drv.h"
+#include "i915_reg.h"
+
+#define I915_CSR_SKL "i915/skl_dmc_ver1.bin"
+
+MODULE_FIRMWARE(I915_CSR_SKL);
+
+/*
+* SKL CSR registers for DC5 and DC6
+*/
+#define CSR_PROGRAM_BASE		0x80000
+#define CSR_SSP_BASE_ADDR_GEN9		0x00002FC0
+#define CSR_HTP_ADDR_SKL		0x00500034
+#define CSR_SSP_BASE			0x8F074
+#define CSR_HTP_SKL			0x8F004
+#define CSR_LAST_WRITE			0x8F034
+#define CSR_LAST_WRITE_VALUE		0xc003b400
+/* MMIO address range for CSR program (0x80000 - 0x82FFF) */
+#define CSR_MAX_FW_SIZE			0x2FFF
+#define CSR_DEFAULT_FW_OFFSET		0xFFFFFFFF
+#define CSR_MMIO_START_RANGE	0x80000
+#define CSR_MMIO_END_RANGE		0x8FFFF
+
+struct intel_css_header {
+	/* 0x09 for DMC */
+	uint32_t module_type;
+
+	/* Includes the DMC specific header in dwords */
+	uint32_t header_len;
+
+	/* always value would be 0x10000 */
+	uint32_t header_ver;
+
+	/* Not used */
+	uint32_t module_id;
+
+	/* Not used */
+	uint32_t module_vendor;
+
+	/* in YYYYMMDD format */
+	uint32_t date;
+
+	/* Size in dwords (CSS_Headerlen + PackageHeaderLen + dmc FWsLen)/4 */
+	uint32_t size;
+
+	/* Not used */
+	uint32_t key_size;
+
+	/* Not used */
+	uint32_t modulus_size;
+
+	/* Not used */
+	uint32_t exponent_size;
+
+	/* Not used */
+	uint32_t reserved1[12];
+
+	/* Major Minor */
+	uint32_t version;
+
+	/* Not used */
+	uint32_t reserved2[8];
+
+	/* Not used */
+	uint32_t kernel_header_info;
+} __packed;
+
+struct intel_fw_info {
+	uint16_t reserved1;
+
+	/* Stepping (A, B, C, ..., *). * is a wildcard */
+	char stepping;
+
+	/* Sub-stepping (0, 1, ..., *). * is a wildcard */
+	char substepping;
+
+	uint32_t offset;
+	uint32_t reserved2;
+} __packed;
+
+struct intel_package_header {
+	/* DMC container header length in dwords */
+	unsigned char header_len;
+
+	/* always value would be 0x01 */
+	unsigned char header_ver;
+
+	unsigned char reserved[10];
+
+	/* Number of valid entries in the FWInfo array below */
+	uint32_t num_entries;
+
+	struct intel_fw_info fw_info[20];
+} __packed;
+
+struct intel_dmc_header {
+	/* always value would be 0x40403E3E */
+	uint32_t signature;
+
+	/* DMC binary header length */
+	unsigned char header_len;
+
+	/* 0x01 */
+	unsigned char header_ver;
+
+	/* Reserved */
+	uint16_t dmcc_ver;
+
+	/* Major, Minor */
+	uint32_t	project;
+
+	/* Firmware program size (excluding header) in dwords */
+	uint32_t	fw_size;
+
+	/* Major Minor version */
+	uint32_t fw_version;
+
+	/* Number of valid MMIO cycles present. */
+	uint32_t mmio_count;
+
+	/* MMIO address */
+	uint32_t mmioaddr[8];
+
+	/* MMIO data */
+	uint32_t mmiodata[8];
+
+	/* FW filename  */
+	unsigned char dfile[32];
+
+	uint32_t reserved1[2];
+} __packed;
+
+struct stepping_info {
+	char stepping;
+	char substepping;
+};
+
+static const struct stepping_info skl_stepping_info[] = {
+		{'A', '0'}, {'B', '0'}, {'C', '0'},
+		{'D', '0'}, {'E', '0'}, {'F', '0'},
+		{'G', '0'}, {'H', '0'}, {'I', '0'}
+};
+
+static char intel_get_stepping(struct drm_device *dev)
+{
+	if (IS_SKYLAKE(dev) && (dev->pdev->revision <
+			ARRAY_SIZE(skl_stepping_info)))
+		return skl_stepping_info[dev->pdev->revision].stepping;
+	else
+		return -ENODATA;
+}
+
+static char intel_get_substepping(struct drm_device *dev)
+{
+	if (IS_SKYLAKE(dev) && (dev->pdev->revision <
+			ARRAY_SIZE(skl_stepping_info)))
+		return skl_stepping_info[dev->pdev->revision].substepping;
+	else
+		return -ENODATA;
+}
+
+void intel_csr_load_program(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	__be32 *payload = dev_priv->csr.dmc_payload;
+	uint32_t i, fw_size;
+
+	if (!IS_GEN9(dev)) {
+		DRM_ERROR("No CSR support available for this platform\n");
+		return;
+	}
+
+	mutex_lock(&dev_priv->csr_lock);
+	fw_size = dev_priv->csr.dmc_fw_size;
+	for (i = 0; i < fw_size; i++)
+		I915_WRITE(CSR_PROGRAM_BASE + i * 4,
+			(u32 __force)payload[i]);
+
+	for (i = 0; i < dev_priv->csr.mmio_count; i++) {
+		I915_WRITE(dev_priv->csr.mmioaddr[i],
+			dev_priv->csr.mmiodata[i]);
+	}
+	mutex_unlock(&dev_priv->csr_lock);
+}
+
+static void finish_csr_load(const struct firmware *fw, void *context)
+{
+	struct drm_i915_private *dev_priv = context;
+	struct drm_device *dev = dev_priv->dev;
+	struct intel_css_header *css_header;
+	struct intel_package_header *package_header;
+	struct intel_dmc_header *dmc_header;
+	struct intel_csr *csr = &dev_priv->csr;
+	char stepping = intel_get_stepping(dev);
+	char substepping = intel_get_substepping(dev);
+	uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
+	uint32_t i;
+	__be32 *dmc_payload;
+
+	if (!fw) {
+		i915_firmware_load_error_print(csr->fw_path, 0);
+		goto out;
+	}
+
+	if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
+		DRM_ERROR("Unknown stepping info, firmware loading failed\n");
+		goto out;
+	}
+
+	/* Extract CSS Header information*/
+	css_header = (struct intel_css_header *)fw->data;
+	if (sizeof(struct intel_css_header) !=
+		(css_header->header_len * 4)) {
+		DRM_ERROR("Firmware has wrong CSS header length %u bytes\n",
+			(css_header->header_len * 4));
+		goto out;
+	}
+	readcount += sizeof(struct intel_css_header);
+
+	/* Extract Package Header information*/
+	package_header = (struct intel_package_header *)
+					&fw->data[readcount];
+	if (sizeof(struct intel_package_header) !=
+		(package_header->header_len * 4)) {
+		DRM_ERROR("Firmware has wrong package header length %u bytes\n",
+			(package_header->header_len * 4));
+		goto out;
+	}
+	readcount += sizeof(struct intel_package_header);
+
+	/* Search for dmc_offset to find firware binary. */
+	for (i = 0; i < package_header->num_entries; i++) {
+		if (package_header->fw_info[i].substepping == '*' &&
+			stepping == package_header->fw_info[i].stepping) {
+			dmc_offset = package_header->fw_info[i].offset;
+			break;
+		} else if (stepping == package_header->fw_info[i].stepping &&
+			substepping == package_header->fw_info[i].substepping) {
+			dmc_offset = package_header->fw_info[i].offset;
+			break;
+		} else if (package_header->fw_info[i].stepping == '*' &&
+			package_header->fw_info[i].substepping == '*')
+			dmc_offset = package_header->fw_info[i].offset;
+	}
+	if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
+		DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
+		goto out;
+	}
+	readcount += dmc_offset;
+
+	/* Extract dmc_header information. */
+	dmc_header = (struct intel_dmc_header *)&fw->data[readcount];
+	if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) {
+		DRM_ERROR("Firmware has wrong dmc header length %u bytes\n",
+				(dmc_header->header_len));
+		goto out;
+	}
+	readcount += sizeof(struct intel_dmc_header);
+
+	/* Cache the dmc header info. */
+	if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) {
+		DRM_ERROR("Firmware has wrong mmio count %u\n",
+						dmc_header->mmio_count);
+		goto out;
+	}
+	csr->mmio_count = dmc_header->mmio_count;
+	for (i = 0; i < dmc_header->mmio_count; i++) {
+		if (dmc_header->mmioaddr[i] < CSR_MMIO_START_RANGE &&
+			dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
+			DRM_ERROR(" Firmware has wrong mmio address 0x%x\n",
+						dmc_header->mmioaddr[i]);
+			goto out;
+		}
+		csr->mmioaddr[i] = dmc_header->mmioaddr[i];
+		csr->mmiodata[i] = dmc_header->mmiodata[i];
+	}
+
+	/* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
+	nbytes = dmc_header->fw_size * 4;
+	if (nbytes > CSR_MAX_FW_SIZE) {
+		DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes);
+		goto out;
+	}
+	csr->dmc_fw_size = dmc_header->fw_size;
+
+	csr->dmc_payload = kmalloc(nbytes, GFP_KERNEL);
+	if (!csr->dmc_payload) {
+		DRM_ERROR("Memory allocation failed for dmc payload\n");
+		goto out;
+	}
+
+	dmc_payload = csr->dmc_payload;
+	for (i = 0; i < dmc_header->fw_size; i++) {
+		uint32_t *tmp = (u32 *)&fw->data[readcount + i * 4];
+		/*
+		 * The firmware payload is an array of 32 bit words stored in
+		 * little-endian format in the firmware image and programmed
+		 * as 32 bit big-endian format to memory.
+		 */
+		dmc_payload[i] = cpu_to_be32(*tmp);
+	}
+
+	/* load csr program during system boot, as needed for DC states */
+	intel_csr_load_program(dev);
+out:
+	release_firmware(fw);
+}
+
+void intel_csr_ucode_init(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_csr *csr = &dev_priv->csr;
+	int ret;
+
+	if (!HAS_CSR(dev))
+		return;
+
+	if (IS_SKYLAKE(dev))
+		csr->fw_path = I915_CSR_SKL;
+	else {
+		DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
+		return;
+	}
+
+	/* CSR supported for platform, load firmware */
+	ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path,
+				&dev_priv->dev->pdev->dev,
+				GFP_KERNEL, dev_priv,
+				finish_csr_load);
+	if (ret)
+		i915_firmware_load_error_print(csr->fw_path, ret);
+
+}
+
+void intel_csr_ucode_fini(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!HAS_CSR(dev))
+		return;
+
+	kfree(dev_priv->csr.dmc_payload);
+}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 7a0aa24..f3a2d88 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1062,6 +1062,11 @@ void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
 unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
 				     struct drm_i915_gem_object *obj);
 
+/* intel_csr.c */
+void intel_csr_ucode_init(struct drm_device *dev);
+void intel_csr_load_program(struct drm_device *dev);
+void intel_csr_ucode_fini(struct drm_device *dev);
+
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
 bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
-- 
2.0.2

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

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

* [PATCH v4 2/8] drm/i915/skl: Add DC5 Trigger Sequence.
  2015-04-16  8:52 [PATCH v4 0/8] Enable DC states for skl Animesh Manna
  2015-04-16  8:52 ` [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
@ 2015-04-16  8:52 ` Animesh Manna
  2015-04-16  9:25   ` Imre Deak
  2015-04-16  8:52 ` [PATCH v4 3/8] drm/i915/skl: Implement enable/disable for Display C5 state Animesh Manna
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Animesh Manna @ 2015-04-16  8:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Suketu Shah

From: Suketu Shah <suketu.j.shah@intel.com>

Add triggers as per expectations mentioned in gen9_enable_dc5
and gen9_disable_dc5 patch.

Also call POSTING_READ for every write to a register to ensure that
its written immediately.

v1: Remove POSTING_READ calls as they've already been added in previous patches.

v2: Rebase to move all runtime pm specific changes to intel_runtime_pm.c file.

Modified as per review comments from Imre:
1] Change variable name 'dc5_allowed' to 'dc5_enabled' to correspond to relevant
   functions.
2] Move the check dc5_enabled in skl_set_power_well() to disable DC5 into
   gen9_disable_DC5 which is a more appropriate place.
3] Convert checks for 'pm.dc5_enabled' and 'pm.suspended' in skl_set_power_well()
   to warnings. However, removing them for now as they'll be included in a future patch
   asserting DC-state entry/exit criteria.
4] Enable DC5, only when CSR firmware is verified to be loaded. Create new structure
   to track 'enabled' and 'deferred' status of DC5.
5] Ensure runtime PM reference is obtained, if CSR is not loaded, to avoid entering
   runtime-suspend and release it when it's loaded.
6] Protect necessary CSR-related code with locks.
7] Move CSR-loading call to runtime PM initialization, as power domains needed to be
   accessed during deferred DC5-enabling, are not initialized earlier.

v3: Rebase to latest.

Modified as per review comments from Imre:
1] Use blocking wait for CSR-loading to finish to enable DC5  for simplicity, instead of
   deferring enabling DC5 until CSR is loaded.
2] Obtain runtime PM reference during CSR-loading initialization itself as deferred DC5-
   enabling is removed and release it at the end of CSR-loading functionality.
3] Revert calling CSR-loading functionality to the beginning of i915 driver-load
   functionality to avoid any delay in loading.
4] Define another variable to track whether CSR-loading failed and use it to avoid enabling
   DC5 if it's true.
5] Define CSR-load-status accessor functions for use later.

v4:
1] Disable DC5 before enabling PG2 instead of after it.
2] DC5 was being mistaken enabled even when CSR-loading timed-out. Fix that.
3] Enable DC5-related functionality using a macro.
4] Remove dc5_enabled tracking variable and its use as it's not needed now.

v5:
1] Mark CSR failed to load where necessary in finish_csr_load function.
2] Use mutex-protected accessor function to check if CSR loaded instead of directly
   accessing the variable.
3] Prefix csr_load_status_get/set function names with intel_.

v6: rebase to latest.
v7: Rebase on top of nightly (Damien)
v8: Squashed the patch from Imre - added csr helper pointers to simplify the code. (Imre)
v9: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)
v10: Added a enum for different csr states, suggested by Imre. (Animesh)

v11: Based on review comments from Imre, Damien and Daniel following changes done
- enum name chnaged to csr_state (singular form).
- FW_UNINITIALIZED used as zeroth element in enum csr_state.
- Prototype changed for helper function(set/get csr status), using enum csr_state instead of bool.

Issue: VIZ-2819
Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
Signed-off-by: Suketu Shah <suketu.j.shah@intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h         |  7 +++++
 drivers/gpu/drm/i915/intel_csr.c        | 49 +++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_drv.h        |  3 ++
 drivers/gpu/drm/i915/intel_runtime_pm.c | 33 ++++++++++++++++++++++
 4 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 90e47a9..670e407 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -667,6 +667,12 @@ struct intel_uncore {
 #define for_each_fw_domain(domain__, dev_priv__, i__) \
 	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
 
+enum csr_state {
+	FW_UNINITIALIZED = 0,
+	FW_LOADED,
+	FW_FAILED
+};
+
 struct intel_csr {
 	const char *fw_path;
 	__be32 *dmc_payload;
@@ -674,6 +680,7 @@ struct intel_csr {
 	uint32_t mmio_count;
 	uint32_t mmioaddr[8];
 	uint32_t mmiodata[8];
+	enum csr_state state;
 };
 
 #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
index f5fa574..fe6789f 100644
--- a/drivers/gpu/drm/i915/intel_csr.c
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -183,6 +183,25 @@ static char intel_get_substepping(struct drm_device *dev)
 		return -ENODATA;
 }
 
+enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv)
+{
+	enum csr_state state;
+
+	mutex_lock(&dev_priv->csr_lock);
+	state = dev_priv->csr.state;
+	mutex_unlock(&dev_priv->csr_lock);
+
+	return state;
+}
+
+void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
+			enum csr_state state)
+{
+	mutex_lock(&dev_priv->csr_lock);
+	dev_priv->csr.state = state;
+	mutex_unlock(&dev_priv->csr_lock);
+}
+
 void intel_csr_load_program(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -204,6 +223,8 @@ void intel_csr_load_program(struct drm_device *dev)
 		I915_WRITE(dev_priv->csr.mmioaddr[i],
 			dev_priv->csr.mmiodata[i]);
 	}
+
+	dev_priv->csr.state = FW_LOADED;
 	mutex_unlock(&dev_priv->csr_lock);
 }
 
@@ -223,11 +244,13 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 
 	if (!fw) {
 		i915_firmware_load_error_print(csr->fw_path, 0);
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 
 	if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
 		DRM_ERROR("Unknown stepping info, firmware loading failed\n");
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 
@@ -237,6 +260,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 		(css_header->header_len * 4)) {
 		DRM_ERROR("Firmware has wrong CSS header length %u bytes\n",
 			(css_header->header_len * 4));
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 	readcount += sizeof(struct intel_css_header);
@@ -248,6 +272,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 		(package_header->header_len * 4)) {
 		DRM_ERROR("Firmware has wrong package header length %u bytes\n",
 			(package_header->header_len * 4));
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 	readcount += sizeof(struct intel_package_header);
@@ -268,6 +293,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 	}
 	if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
 		DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 	readcount += dmc_offset;
@@ -277,6 +303,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 	if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) {
 		DRM_ERROR("Firmware has wrong dmc header length %u bytes\n",
 				(dmc_header->header_len));
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 	readcount += sizeof(struct intel_dmc_header);
@@ -285,6 +312,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 	if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) {
 		DRM_ERROR("Firmware has wrong mmio count %u\n",
 						dmc_header->mmio_count);
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 	csr->mmio_count = dmc_header->mmio_count;
@@ -293,6 +321,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 			dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
 			DRM_ERROR(" Firmware has wrong mmio address 0x%x\n",
 						dmc_header->mmioaddr[i]);
+			intel_csr_load_status_set(dev_priv, FW_FAILED);
 			goto out;
 		}
 		csr->mmioaddr[i] = dmc_header->mmioaddr[i];
@@ -303,6 +332,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 	nbytes = dmc_header->fw_size * 4;
 	if (nbytes > CSR_MAX_FW_SIZE) {
 		DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes);
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 	csr->dmc_fw_size = dmc_header->fw_size;
@@ -310,6 +340,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 	csr->dmc_payload = kmalloc(nbytes, GFP_KERNEL);
 	if (!csr->dmc_payload) {
 		DRM_ERROR("Memory allocation failed for dmc payload\n");
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		goto out;
 	}
 
@@ -327,6 +358,11 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 	/* load csr program during system boot, as needed for DC states */
 	intel_csr_load_program(dev);
 out:
+	/*
+	 * Release the runtime pm reference obtained when
+	 * CSR wasn't loaded.
+	 */
+	intel_runtime_pm_put(dev_priv);
 	release_firmware(fw);
 }
 
@@ -343,17 +379,25 @@ void intel_csr_ucode_init(struct drm_device *dev)
 		csr->fw_path = I915_CSR_SKL;
 	else {
 		DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		return;
 	}
 
+	/*
+	 * Obtain a runtime pm reference, until CSR is loaded,
+	 * to avoid entering runtime-suspend.
+	 */
+	intel_runtime_pm_get(dev_priv);
+
 	/* CSR supported for platform, load firmware */
 	ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path,
 				&dev_priv->dev->pdev->dev,
 				GFP_KERNEL, dev_priv,
 				finish_csr_load);
-	if (ret)
+	if (ret) {
 		i915_firmware_load_error_print(csr->fw_path, ret);
-
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
+	}
 }
 
 void intel_csr_ucode_fini(struct drm_device *dev)
@@ -363,5 +407,6 @@ void intel_csr_ucode_fini(struct drm_device *dev)
 	if (!HAS_CSR(dev))
 		return;
 
+	intel_csr_load_status_set(dev_priv, FW_FAILED);
 	kfree(dev_priv->csr.dmc_payload);
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f3a2d88..25d7956 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1064,6 +1064,9 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
 
 /* intel_csr.c */
 void intel_csr_ucode_init(struct drm_device *dev);
+enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv);
+void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
+					enum csr_state state);
 void intel_csr_load_program(struct drm_device *dev);
 void intel_csr_ucode_fini(struct drm_device *dev);
 
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index ce00e69..23f02a8 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -49,6 +49,8 @@
  * present for a given platform.
  */
 
+#define GEN9_ENABLE_DC5(dev) (IS_SKYLAKE(dev))
+
 #define for_each_power_well(i, power_well, domain_mask, power_domains)	\
 	for (i = 0;							\
 	     i < (power_domains)->power_well_count &&			\
@@ -319,9 +321,20 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
 	SKL_DISPLAY_MISC_IO_POWER_DOMAINS)) |		\
 	BIT(POWER_DOMAIN_INIT))
 
+static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
+{
+	/* TODO: Implementation to be done. */
+}
+
+static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
+{
+	/* TODO: Implementation to be done. */
+}
+
 static void skl_set_power_well(struct drm_i915_private *dev_priv,
 			struct i915_power_well *power_well, bool enable)
 {
+	struct drm_device *dev = dev_priv->dev;
 	uint32_t tmp, fuse_status;
 	uint32_t req_mask, state_mask;
 	bool is_enabled, enable_requested, check_fuse_status = false;
@@ -361,6 +374,13 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
 
 	if (enable) {
 		if (!enable_requested) {
+			WARN((tmp & state_mask) &&
+				!I915_READ(HSW_PWR_WELL_BIOS),
+				"Invalid for power well status to be enabled, unless done by the BIOS, \
+				when request is to disable!\n");
+			if (GEN9_ENABLE_DC5(dev) &&
+				power_well->data == SKL_DISP_PW_2)
+				gen9_disable_dc5(dev_priv);
 			I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask);
 		}
 
@@ -377,6 +397,19 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
 			I915_WRITE(HSW_PWR_WELL_DRIVER,	tmp & ~req_mask);
 			POSTING_READ(HSW_PWR_WELL_DRIVER);
 			DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
+
+			if (GEN9_ENABLE_DC5(dev) &&
+				power_well->data == SKL_DISP_PW_2) {
+				enum csr_state state;
+
+				wait_for((state = intel_csr_load_status_get(dev_priv)) !=
+						FW_UNINITIALIZED, 1000);
+				if (state != FW_LOADED)
+					DRM_ERROR("CSR firmware not ready (%d)\n",
+							state);
+				else
+					gen9_enable_dc5(dev_priv);
+			}
 		}
 	}
 
-- 
2.0.2

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

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

* [PATCH v4 3/8] drm/i915/skl: Implement enable/disable for Display C5 state.
  2015-04-16  8:52 [PATCH v4 0/8] Enable DC states for skl Animesh Manna
  2015-04-16  8:52 ` [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
  2015-04-16  8:52 ` [PATCH v4 2/8] drm/i915/skl: Add DC5 Trigger Sequence Animesh Manna
@ 2015-04-16  8:52 ` Animesh Manna
  2015-04-30 13:21   ` Imre Deak
  2015-04-16  8:52 ` [PATCH v4 4/8] drm/i915/skl: Assert the requirements to enter or exit DC5 Animesh Manna
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Animesh Manna @ 2015-04-16  8:52 UTC (permalink / raw)
  To: intel-gfx

From: "A.Sunil Kamath" <sunil.kamath@intel.com>

This patch just implements the basic enable and disable
functions of DC5 state which is needed for both SKL and BXT.

Its important to load respective CSR program before calling
enable, which anyways will happen as CSR program is executed
during boot.

DC5 is a power saving state where hardware dynamically disables
power well 1 and the CDCLK PLL and saves the associated registers.

DC5 can be entered when software allows it, power well 2 is
disabled, and hardware detects that all pipes are disabled
or pipe A is enabled with PSR active.

Its better to configure display engine to have power well 2 disabled before
getting into DC5 enable function. Hence rpm framework will have to
ensure to check status of power well 2 before calling gen9_enable_dc5.

Rather dc5 entry criteria should be decided based on power well 2 status.
If disabled, then call gen9_enable_dc5.

v2: Replace HAS_ with IS_ check as per Daniel's review comments

v3: Cleared the bits dc5/dc6 enable of DC_STATE_EN register
before setting them as per Satheesh's review comments.

v4: call POSTING_READ for every write to a register to ensure that
its written immediately.

v5: Modified as per review comments from Imre.
- Squashed register definitions into this patch.
- Finetuned comments and functions.

v6:
Avoid redundant writes in gen9_set_dc_state_debugmask_memory_up function.

v7:
1] Rebase to latest.
2] Move all runtime PM functions defined in intel_display.c to
   intel_runtime_pm.c.

v8: Rebased to drm-intel-nightly. (Animesh)

Issue: VIZ-2819
Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h         | 11 +++++++++
 drivers/gpu/drm/i915/intel_runtime_pm.c | 41 +++++++++++++++++++++++++++++++--
 2 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 596e8eb..dcb8528 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -6792,6 +6792,17 @@ enum skl_disp_power_wells {
 #define GET_CFG_CR1_REG(id) (DPLL1_CFGCR1 + (id - SKL_DPLL1) * 8)
 #define GET_CFG_CR2_REG(id) (DPLL1_CFGCR2 + (id - SKL_DPLL1) * 8)
 
+/*
+* SKL DC
+*/
+#define  DC_STATE_EN			0x45504
+#define  DC_STATE_EN_UPTO_DC5		(1<<0)
+#define  DC_STATE_EN_UPTO_DC6		(2<<0)
+#define  DC_STATE_EN_UPTO_DC5_DC6_MASK   0x3
+
+#define  DC_STATE_DEBUG                  0x45520
+#define  DC_STATE_DEBUG_MASK_MEMORY_UP	(1<<1)
+
 /* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this register,
  * since on HSW we can't write to it using I915_WRITE. */
 #define D_COMP_HSW			(MCHBAR_MIRROR_BASE_SNB + 0x5F0C)
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 23f02a8..466ea69 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -321,14 +321,51 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
 	SKL_DISPLAY_MISC_IO_POWER_DOMAINS)) |		\
 	BIT(POWER_DOMAIN_INIT))
 
+static void gen9_set_dc_state_debugmask_memory_up(
+			struct drm_i915_private *dev_priv)
+{
+	uint32_t val;
+
+	/* The below bit doesn't need to be cleared ever afterwards */
+	val = I915_READ(DC_STATE_DEBUG);
+	if (!(val & DC_STATE_DEBUG_MASK_MEMORY_UP)) {
+		val |= DC_STATE_DEBUG_MASK_MEMORY_UP;
+		I915_WRITE(DC_STATE_DEBUG, val);
+		POSTING_READ(DC_STATE_DEBUG);
+	}
+}
+
 static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
 {
-	/* TODO: Implementation to be done. */
+	struct drm_device *dev = dev_priv->dev;
+	uint32_t val;
+
+	WARN_ON(!IS_GEN9(dev));
+
+	DRM_DEBUG_KMS("Enabling DC5\n");
+
+	gen9_set_dc_state_debugmask_memory_up(dev_priv);
+
+	val = I915_READ(DC_STATE_EN);
+	val &= ~DC_STATE_EN_UPTO_DC5_DC6_MASK;
+	val |= DC_STATE_EN_UPTO_DC5;
+	I915_WRITE(DC_STATE_EN, val);
+	POSTING_READ(DC_STATE_EN);
 }
 
 static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
 {
-	/* TODO: Implementation to be done. */
+	struct drm_device *dev = dev_priv->dev;
+	uint32_t val;
+
+	WARN_ON(!IS_GEN9(dev));
+
+	DRM_DEBUG_KMS("Disabling DC5\n");
+
+	val = I915_READ(DC_STATE_EN);
+	val &= ~DC_STATE_EN_UPTO_DC5;
+	I915_WRITE(DC_STATE_EN, val);
+	POSTING_READ(DC_STATE_EN);
 }
 
 static void skl_set_power_well(struct drm_i915_private *dev_priv,
-- 
2.0.2

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

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

* [PATCH v4 4/8] drm/i915/skl: Assert the requirements to enter or exit DC5.
  2015-04-16  8:52 [PATCH v4 0/8] Enable DC states for skl Animesh Manna
                   ` (2 preceding siblings ...)
  2015-04-16  8:52 ` [PATCH v4 3/8] drm/i915/skl: Implement enable/disable for Display C5 state Animesh Manna
@ 2015-04-16  8:52 ` Animesh Manna
  2015-04-30 13:26   ` Imre Deak
  2015-04-16  8:52 ` [PATCH v4 5/8] drm/i915/skl: Add DC6 Trigger sequence Animesh Manna
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Animesh Manna @ 2015-04-16  8:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Suketu Shah

From: Suketu Shah <suketu.j.shah@intel.com>

Warn if the conditions to enter or exit DC5 are not satisfied such
as support for runtime PM, state of power well, CSR loading etc.

v2: Removed camelcase in functions and variables.

v3: Do some minimal check to assert if CSR program is not loaded.

v4:
1] Used an appropriate function lookup_power_well() to identify power well,
instead of using a magic number which can change in future.
2] Split the conditions further in assert_can_enable_DC5() and added more checks.
3] Removed all WARNs from assert_can_disable_DC5 as they were unnecessary and added two
   new ones.
4] Changed variable names as updated in earlier patches.

v5:
1] Change lookup_power_well function to take an int power well id.
2] Define a new intel_display_power_well_is_enabled helper function to check whether a
   particular power well is enabled.
3] Use CSR-related mutex in assert_csr_loaded function.

v6: Remove use of dc5_enabled variable as it's no longer needed.

v7:
1] Rebase to latest.
2] Move all DC5-related functions from intel_display.c to intel_runtime_pm.c.

v8: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)

v9: Modified below changes based on review comments from Imre.
- Moved intel_display_power_well_is_enabled() to intel_runtime_pm.c.
- Removed mutex lock from assert_csr_loaded(). (Animesh)

Issue: VIZ-2819
Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
Signed-off-by: Suketu Shah <suketu.j.shah@intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
---
 drivers/gpu/drm/i915/intel_csr.c        |  9 ++++++
 drivers/gpu/drm/i915/intel_drv.h        |  1 +
 drivers/gpu/drm/i915/intel_runtime_pm.c | 51 +++++++++++++++++++++++++++++----
 3 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
index fe6789f..d58effe 100644
--- a/drivers/gpu/drm/i915/intel_csr.c
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -410,3 +410,12 @@ void intel_csr_ucode_fini(struct drm_device *dev)
 	intel_csr_load_status_set(dev_priv, FW_FAILED);
 	kfree(dev_priv->csr.dmc_payload);
 }
+
+void assert_csr_loaded(struct drm_i915_private *dev_priv)
+{
+	WARN((intel_csr_load_status_get(dev_priv) != FW_LOADED), "CSR is not loaded.\n");
+	WARN(!I915_READ(CSR_PROGRAM_BASE),
+				"CSR program storage start is NULL\n");
+	WARN(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n");
+	WARN(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n");
+}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 25d7956..2eb0169 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1069,6 +1069,7 @@ void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
 					enum csr_state state);
 void intel_csr_load_program(struct drm_device *dev);
 void intel_csr_ucode_fini(struct drm_device *dev);
+void assert_csr_loaded(struct drm_i915_private *dev_priv);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 466ea69..da8c18d 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -64,6 +64,9 @@
 	     i--)							 \
 		if ((power_well)->domains & (domain_mask))
 
+bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
+				    int power_well_id);
+
 /*
  * We should only use the power well if we explicitly asked the hardware to
  * enable it, so check if it's enabled and also check if we've requested it to
@@ -335,12 +338,39 @@ static void gen9_set_dc_state_debugmask_memory_up(
 	}
 }
 
-static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
+static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
+	bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv,
+					SKL_DISP_PW_2);
+
+	WARN(!IS_SKYLAKE(dev), "Platform doesn't support DC5.\n");
+	WARN(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n");
+	WARN(pg2_enabled, "PG2 not disabled to enable DC5.\n");
+
+	WARN((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5),
+				"DC5 already programmed to be enabled.\n");
+	WARN(dev_priv->pm.suspended,
+		"DC5 cannot be enabled, if platform is runtime-suspended.\n");
+
+	assert_csr_loaded(dev_priv);
+}
+
+static void assert_can_disable_dc5(struct drm_i915_private *dev_priv)
+{
+	bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv,
+					SKL_DISP_PW_2);
+
+	WARN(!pg2_enabled, "PG2 not enabled to disable DC5.\n");
+	WARN(dev_priv->pm.suspended,
+		"Disabling of DC5 while platform is runtime-suspended should never happen.\n");
+}
+
+static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
+{
 	uint32_t val;
 
-	WARN_ON(!IS_GEN9(dev));
+	assert_can_enable_dc5(dev_priv);
 
 	DRM_DEBUG_KMS("Enabling DC5\n");
 
@@ -355,10 +385,9 @@ static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
 
 static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
 	uint32_t val;
 
-	WARN_ON(!IS_GEN9(dev));
+	assert_can_disable_dc5(dev_priv);
 
 	DRM_DEBUG_KMS("Disabling DC5\n");
 
@@ -1318,7 +1347,7 @@ static struct i915_power_well chv_power_wells[] = {
 };
 
 static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv,
-						 enum punit_power_well power_well_id)
+						 int power_well_id)
 {
 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
 	struct i915_power_well *power_well;
@@ -1332,6 +1361,18 @@ static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_pr
 	return NULL;
 }
 
+bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
+				    int power_well_id)
+{
+	struct i915_power_well *power_well;
+	bool ret;
+
+	power_well = lookup_power_well(dev_priv, power_well_id);
+	ret = power_well->ops->is_enabled(dev_priv, power_well);
+
+	return ret;
+}
+
 static struct i915_power_well skl_power_wells[] = {
 	{
 		.name = "always-on",
-- 
2.0.2

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

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

* [PATCH v4 5/8] drm/i915/skl: Add DC6 Trigger sequence.
  2015-04-16  8:52 [PATCH v4 0/8] Enable DC states for skl Animesh Manna
                   ` (3 preceding siblings ...)
  2015-04-16  8:52 ` [PATCH v4 4/8] drm/i915/skl: Assert the requirements to enter or exit DC5 Animesh Manna
@ 2015-04-16  8:52 ` Animesh Manna
  2015-04-30 13:41   ` Imre Deak
                     ` (2 more replies)
  2015-04-16  8:52 ` [PATCH v4 6/8] Implement enable/disable for Display C6 state Animesh Manna
                   ` (3 subsequent siblings)
  8 siblings, 3 replies; 37+ messages in thread
From: Animesh Manna @ 2015-04-16  8:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Suketu Shah

From: Suketu Shah <suketu.j.shah@intel.com>

Add triggers for DC6 as per details provided in skl_enable_dc6
and skl_disable_dc6 implementations.

Also Call POSTING_READ for every write to a register to ensure
it is written to immediately

v1: Remove POSTING_READ and intel_prepare_ddi calls as they've been added in previous patches.

v2:
1] Remove check for backlight disabled as it should be the case by that time.
2] Mark DC5 as disabled when enabling DC6.
3] Return from DC5-disabling function early if DC5 is already be disabled which can happen
   due to DC6-enabling earlier.
3] Ensure CSR firmware is loaded after resume from DC6 as corresponding memory contents won't
   be retained after runtime-suspend.
4] Ensure that CSR isn't identified as loaded before CSR-loading program is called during
   runtime-resume.

v3: Rebase to latest
Modified as per review comments from Imre and after discussion with Art:
1] DC6 should be preferably enabled when PG2 is disabled by SW as the check for PG1 being
   disabled is taken of by HW to enter DC6, and disabled when PG2 is enabled respectively.
   This helps save more power, especially in the case when display is disabled but GT is
   enabled. Accordingly, replacing DC5 trigger sequence with DC6 for SKL.
2] DC6 could be enabled from intel_runtime_suspend() function, if DC5 is already enabled.
3] Move CSR-load-status setting code from intel_runtime_suspend function to a new function.

v4:
1] Enable/disable DC6 only when toggling the power-well using a newly defined macro ENABLE_DC6.

v5:
1] Load CSR on system resume too as firmware may be lost on system suspend preventing
   enabling DC5, DC6.
2] DDI buffers shouldn't be programmed during driver-load/resume as it's already done
   during modeset initialization then and also that the encoder list is still uninitialized by
   then. Therefore, call intel_prepare_ddi function right after disabling DC6 but outside
   skl_disable_dc6 function and not during driver-load/resume.

v6:
1] Rebase to latest.
2] Move SKL_ENABLE_DC6 macro definition from intel_display.c to intel_runtime_pm.c.

v7:
1) Refactored the code for removing the warning got from checkpatch.
2) After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)

v8:
- Reverted the changes done in v7.
- Removed the condition check in skl_prepare_resune(). (Animesh)

Issue: VIZ-2819
Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
Signed-off-by: Suketu Shah <suketu.j.shah@intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c         | 30 +++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_runtime_pm.c | 43 +++++++++++++++++++++++++++------
 2 files changed, 66 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index acd0e2b..0f590e3 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -594,6 +594,8 @@ static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
 static int intel_suspend_complete(struct drm_i915_private *dev_priv);
 static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
 			      bool rpm_resume);
+static int skl_resume_prepare(struct drm_i915_private *dev_priv);
+
 
 static int i915_drm_suspend(struct drm_device *dev)
 {
@@ -808,6 +810,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
 
 	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		hsw_disable_pc8(dev_priv);
+	else if (IS_SKYLAKE(dev_priv))
+		ret = skl_resume_prepare(dev_priv);
 
 	intel_uncore_sanitize(dev);
 	intel_power_domains_init_hw(dev_priv);
@@ -1022,6 +1026,19 @@ static int i915_pm_resume(struct device *dev)
 	return i915_drm_resume(drm_dev);
 }
 
+static int skl_suspend_complete(struct drm_i915_private *dev_priv)
+{
+	/* Enabling DC6 is not a hard requirement to enter runtime D3 */
+
+	/*
+	 * This is to ensure that CSR isn't identified as loaded before
+	 * CSR-loading program is called during runtime-resume.
+	 */
+	intel_csr_load_status_set(dev_priv, FW_UNINITIALIZED);
+
+	return 0;
+}
+
 static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
 {
 	hsw_enable_pc8(dev_priv);
@@ -1029,6 +1046,15 @@ static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
 	return 0;
 }
 
+static int skl_resume_prepare(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+
+	intel_csr_load_program(dev);
+
+	return 0;
+}
+
 /*
  * Save all Gunit registers that may be lost after a D3 and a subsequent
  * S0i[R123] transition. The list of registers needing a save/restore is
@@ -1487,6 +1513,8 @@ static int intel_runtime_resume(struct device *device)
 
 	if (IS_GEN6(dev_priv))
 		intel_init_pch_refclk(dev);
+	else if (IS_SKYLAKE(dev))
+		ret = skl_resume_prepare(dev_priv);
 	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		hsw_disable_pc8(dev_priv);
 	else if (IS_VALLEYVIEW(dev_priv))
@@ -1519,6 +1547,8 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv)
 	struct drm_device *dev = dev_priv->dev;
 	int ret;
 
+	if (IS_SKYLAKE(dev))
+		ret = skl_suspend_complete(dev_priv);
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		ret = hsw_suspend_complete(dev_priv);
 	else if (IS_VALLEYVIEW(dev))
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index da8c18d..7e6908e 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -49,7 +49,8 @@
  * present for a given platform.
  */
 
-#define GEN9_ENABLE_DC5(dev) (IS_SKYLAKE(dev))
+#define GEN9_ENABLE_DC5(dev) 0
+#define SKL_ENABLE_DC6(dev) IS_SKYLAKE(dev)
 
 #define for_each_power_well(i, power_well, domain_mask, power_domains)	\
 	for (i = 0;							\
@@ -397,6 +398,16 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
 	POSTING_READ(DC_STATE_EN);
 }
 
+static void skl_enable_dc6(struct drm_i915_private *dev_priv)
+{
+	/* TODO: Implementation to be done. */
+}
+
+static void skl_disable_dc6(struct drm_i915_private *dev_priv)
+{
+	/* TODO: Implementation to be done. */
+}
+
 static void skl_set_power_well(struct drm_i915_private *dev_priv,
 			struct i915_power_well *power_well, bool enable)
 {
@@ -444,9 +455,21 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
 				!I915_READ(HSW_PWR_WELL_BIOS),
 				"Invalid for power well status to be enabled, unless done by the BIOS, \
 				when request is to disable!\n");
-			if (GEN9_ENABLE_DC5(dev) &&
-				power_well->data == SKL_DISP_PW_2)
-				gen9_disable_dc5(dev_priv);
+			if ((GEN9_ENABLE_DC5(dev) || SKL_ENABLE_DC6(dev)) &&
+				power_well->data == SKL_DISP_PW_2) {
+				if (SKL_ENABLE_DC6(dev)) {
+					skl_disable_dc6(dev_priv);
+					/*
+					 * DDI buffer programming unnecessary during driver-load/resume
+					 * as it's already done during modeset initialization then.
+					 * It's also invalid here as encoder list is still uninitialized.
+					 */
+					if (!dev_priv->power_domains.initializing)
+						intel_prepare_ddi(dev);
+				} else {
+					gen9_disable_dc5(dev_priv);
+				}
+			}
 			I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask);
 		}
 
@@ -464,17 +487,23 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
 			POSTING_READ(HSW_PWR_WELL_DRIVER);
 			DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
 
-			if (GEN9_ENABLE_DC5(dev) &&
+			if ((GEN9_ENABLE_DC5(dev) || SKL_ENABLE_DC6(dev)) &&
 				power_well->data == SKL_DISP_PW_2) {
 				enum csr_state state;
-
+				/* TODO: wait for a completion event or
+				 * similar here instead of busy
+				 * waiting using wait_for function.
+				 */
 				wait_for((state = intel_csr_load_status_get(dev_priv)) !=
 						FW_UNINITIALIZED, 1000);
 				if (state != FW_LOADED)
 					DRM_ERROR("CSR firmware not ready (%d)\n",
 							state);
 				else
-					gen9_enable_dc5(dev_priv);
+					if (SKL_ENABLE_DC6(dev))
+						skl_enable_dc6(dev_priv);
+					else
+						gen9_enable_dc5(dev_priv);
 			}
 		}
 	}
-- 
2.0.2

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

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

* [PATCH v4 6/8] Implement enable/disable for Display C6 state
  2015-04-16  8:52 [PATCH v4 0/8] Enable DC states for skl Animesh Manna
                   ` (4 preceding siblings ...)
  2015-04-16  8:52 ` [PATCH v4 5/8] drm/i915/skl: Add DC6 Trigger sequence Animesh Manna
@ 2015-04-16  8:52 ` Animesh Manna
  2015-04-30 13:45   ` Imre Deak
  2015-04-16  8:52 ` [PATCH v4 7/8] drm/i915/skl: Assert the requirements to enter or exit DC6 Animesh Manna
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 37+ messages in thread
From: Animesh Manna @ 2015-04-16  8:52 UTC (permalink / raw)
  To: intel-gfx

From: "A.Sunil Kamath" <sunil.kamath@intel.com>

This patch just implements the basic enable and disable
functions of DC6 state which is needed for SKL platform.

Its important to load SKL CSR program before calling enable.

DC6 is a deeper power saving state where hardware dynamically
disables power well 0 and saves the associated registers.
DC6 can be entered when software allows it, the conditions
for DC5 are met, and the PCU allows DC6.
DC6 cannot be used if the backlight is being driven from the
display utility pin.

Its better to configure display engine to have power well 2
disabled before getting into DC6 enable function. Hence rpm
framework will ensure to check status of power well 2 and DC5
before calling skl_enable_dc6.

v2: Replace HAS_ with IS_ check as per Daniel's review comments

v3: Cleared the bits dc5/dc6 enable of DC_STATE_EN register
before setting them as per Satheesh's review comments.

v4: No need to call gen9_disable_dc5 inside enable sequence of
DC6, as its already take care above.

v5: call POSTING_READ for every write to a register to ensure that
its written immediately.
Call intel_prepare_ddi during DC6 exit as it's required on low-power exit.

v6: Protect DC6-enabling-disabling functionality with locks to synchronize
with CSR-loading code.

v7: Remove grabbing CSR-related mutex in skl_enable/disable_dc6 functions as
    deferred DC5-enabling functionality is now removed.

v8: Remove 'Disabling DC5' from the debug comment during DC6 enabling as when
    DC6 is allowed, DC5 is not programmed at all.

v9:
1] Rebase to latest.
2] Move all DC6-related functions from intel_display.c to intel_runtime_pm.c.

v10: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)

Issue: VIZ-2819
Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
---
 drivers/gpu/drm/i915/intel_runtime_pm.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 7e6908e..ba49795 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -400,12 +400,35 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
 
 static void skl_enable_dc6(struct drm_i915_private *dev_priv)
 {
-	/* TODO: Implementation to be done. */
+	struct drm_device *dev = dev_priv->dev;
+	uint32_t val;
+
+	WARN_ON(!IS_SKYLAKE(dev));
+
+	DRM_DEBUG_KMS("Enabling DC6\n");
+
+	gen9_set_dc_state_debugmask_memory_up(dev_priv);
+
+	val = I915_READ(DC_STATE_EN);
+	val &= ~DC_STATE_EN_UPTO_DC5_DC6_MASK;
+	val |= DC_STATE_EN_UPTO_DC6;
+	I915_WRITE(DC_STATE_EN, val);
+	POSTING_READ(DC_STATE_EN);
 }
 
 static void skl_disable_dc6(struct drm_i915_private *dev_priv)
 {
-	/* TODO: Implementation to be done. */
+	struct drm_device *dev = dev_priv->dev;
+	uint32_t val;
+
+	WARN_ON(!IS_SKYLAKE(dev));
+
+	DRM_DEBUG_KMS("Disabling DC6\n");
+
+	val = I915_READ(DC_STATE_EN);
+	val &= ~DC_STATE_EN_UPTO_DC6;
+	I915_WRITE(DC_STATE_EN, val);
+	POSTING_READ(DC_STATE_EN);
 }
 
 static void skl_set_power_well(struct drm_i915_private *dev_priv,
-- 
2.0.2

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

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

* [PATCH v4 7/8] drm/i915/skl: Assert the requirements to enter or exit DC6.
  2015-04-16  8:52 [PATCH v4 0/8] Enable DC states for skl Animesh Manna
                   ` (5 preceding siblings ...)
  2015-04-16  8:52 ` [PATCH v4 6/8] Implement enable/disable for Display C6 state Animesh Manna
@ 2015-04-16  8:52 ` Animesh Manna
  2015-04-16  8:52 ` [PATCH v4 8/8] drm/i915/skl: Enable runtime PM Animesh Manna
  2015-05-04 13:12 ` [PATCH v4 0/8] Enable DC states for skl Daniel Vetter
  8 siblings, 0 replies; 37+ messages in thread
From: Animesh Manna @ 2015-04-16  8:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Suketu Shah

From: Suketu Shah <suketu.j.shah@intel.com>

Warn if the conditions to enter or exit DC6 are not satisfied such
as support for runtime PM, state of power well, CSR loading etc.

v2: Removed camelcase in functions and variables.

v3: Do some minimal check to assert if CSR program is not loaded.

v4:
1] Correct the check for backlight-disabling in assert_can_enable_dc6().
2] Check csr.loaded = false before disabling DC6 and simplify other checks.

v5:
1] Remove checks for DC5 state from assert_can_enable_dc6 function as DC5 is no
   longer enabled before enabling DC6.
2] Correct the check for CSR-loading in assert_can_disable_dc6 function as CSR must
   be loaded for context restore to happen on DC6 disabling.

v6:
1] It's okay to explicitly disable DC6 during driver-load/resume even though it might
   already be disabled and so don't warn about it.

v7: Rebase to latest.

v8: Sqashed the patch from Imre -
[PATCH] drm/i915/skl: avoid false CSR fw not loaded WARN during driver load/resume

v9: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)

v10: During initialization added a early return before disabling DC5. (Animesh)

Issue: VIZ-2819
Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
Signed-off-by: Suketu Shah <suketu.j.shah@intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_runtime_pm.c | 40 +++++++++++++++++++++++++++++----
 1 file changed, 36 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index ba49795..6bbf9ec 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -361,6 +361,12 @@ static void assert_can_disable_dc5(struct drm_i915_private *dev_priv)
 {
 	bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv,
 					SKL_DISP_PW_2);
+	/*
+	 * During initialization, the firmware may not be loaded yet.
+	 * We still want to make sure that the DC enabling flag is cleared.
+	 */
+	if (dev_priv->power_domains.initializing)
+		return;
 
 	WARN(!pg2_enabled, "PG2 not enabled to disable DC5.\n");
 	WARN(dev_priv->pm.suspended,
@@ -398,12 +404,39 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
 	POSTING_READ(DC_STATE_EN);
 }
 
-static void skl_enable_dc6(struct drm_i915_private *dev_priv)
+static void assert_can_enable_dc6(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
+
+	WARN(!IS_SKYLAKE(dev), "Platform doesn't support DC6.\n");
+	WARN(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n");
+	WARN(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE,
+		"Backlight is not disabled.\n");
+	WARN((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6),
+		"DC6 already programmed to be enabled.\n");
+
+	assert_csr_loaded(dev_priv);
+}
+
+static void assert_can_disable_dc6(struct drm_i915_private *dev_priv)
+{
+	/*
+	 * During initialization, the firmware may not be loaded yet.
+	 * We still want to make sure that the DC enabling flag is cleared.
+	 */
+	if (dev_priv->power_domains.initializing)
+		return;
+
+	assert_csr_loaded(dev_priv);
+	WARN(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6),
+		"DC6 already programmed to be disabled.\n");
+}
+
+static void skl_enable_dc6(struct drm_i915_private *dev_priv)
+{
 	uint32_t val;
 
-	WARN_ON(!IS_SKYLAKE(dev));
+	assert_can_enable_dc6(dev_priv);
 
 	DRM_DEBUG_KMS("Enabling DC6\n");
 
@@ -418,10 +451,9 @@ static void skl_enable_dc6(struct drm_i915_private *dev_priv)
 
 static void skl_disable_dc6(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
 	uint32_t val;
 
-	WARN_ON(!IS_SKYLAKE(dev));
+	assert_can_disable_dc6(dev_priv);
 
 	DRM_DEBUG_KMS("Disabling DC6\n");
 
-- 
2.0.2

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

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

* [PATCH v4 8/8] drm/i915/skl: Enable runtime PM
  2015-04-16  8:52 [PATCH v4 0/8] Enable DC states for skl Animesh Manna
                   ` (6 preceding siblings ...)
  2015-04-16  8:52 ` [PATCH v4 7/8] drm/i915/skl: Assert the requirements to enter or exit DC6 Animesh Manna
@ 2015-04-16  8:52 ` Animesh Manna
  2015-04-17  1:52   ` shuang.he
  2015-04-30 13:47   ` Imre Deak
  2015-05-04 13:12 ` [PATCH v4 0/8] Enable DC states for skl Daniel Vetter
  8 siblings, 2 replies; 37+ messages in thread
From: Animesh Manna @ 2015-04-16  8:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Suketu Shah

From: Suketu Shah <suketu.j.shah@intel.com>

Enable runtime PM for Skylake platform

v2: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)

Issue: VIZ-2819
Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
Signed-off-by: Suketu Shah <suketu.j.shah@intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 670e407..e8d27eb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2442,7 +2442,8 @@ struct drm_i915_cmd_table {
 				 IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || \
 				 IS_SKYLAKE(dev))
 #define HAS_RUNTIME_PM(dev)	(IS_GEN6(dev) || IS_HASWELL(dev) || \
-				 IS_BROADWELL(dev) || IS_VALLEYVIEW(dev))
+				 IS_BROADWELL(dev) || IS_VALLEYVIEW(dev) || \
+				 IS_SKYLAKE(dev))
 #define HAS_RC6(dev)		(INTEL_INFO(dev)->gen >= 6)
 #define HAS_RC6p(dev)		(INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
 
-- 
2.0.2

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

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

* Re: [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware.
  2015-04-16  8:52 ` [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
@ 2015-04-16  9:18   ` Damien Lespiau
  2015-04-16  9:21   ` Imre Deak
  2015-04-28 14:45   ` Imre Deak
  2 siblings, 0 replies; 37+ messages in thread
From: Damien Lespiau @ 2015-04-16  9:18 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx

On Thu, Apr 16, 2015 at 02:22:07PM +0530, Animesh Manna wrote:
> +#define I915_CSR_SKL "i915/skl_dmc_ver1.bin"

This needs to be skl_dmc_ver4.bin, because that's the version we made
public.

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

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

* Re: [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware.
  2015-04-16  8:52 ` [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
  2015-04-16  9:18   ` Damien Lespiau
@ 2015-04-16  9:21   ` Imre Deak
  2015-04-16 11:59     ` Animesh Manna
  2015-04-28 14:45   ` Imre Deak
  2 siblings, 1 reply; 37+ messages in thread
From: Imre Deak @ 2015-04-16  9:21 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx

On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
> [...]
> +#include <linux/firmware.h>
> +#include "i915_drv.h"
> +#include "i915_reg.h"
> +
> +#define I915_CSR_SKL "i915/skl_dmc_ver1.bin"

The latest version on the FW download page is skl_dmc_ver4.bin as Damien
pointed out and skl_dmc_ver1.bin is not available there. So why did you
choose ver1? If ver4 is not compatible with the current driver code,
then ver1 must be made available too on the download page, otherwise we
should use here ver4.

The patch otherwise looks ok to me.

--Imre

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

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

* Re: [PATCH v4 2/8] drm/i915/skl: Add DC5 Trigger Sequence.
  2015-04-16  8:52 ` [PATCH v4 2/8] drm/i915/skl: Add DC5 Trigger Sequence Animesh Manna
@ 2015-04-16  9:25   ` Imre Deak
  2015-04-16  9:48     ` Imre Deak
  0 siblings, 1 reply; 37+ messages in thread
From: Imre Deak @ 2015-04-16  9:25 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
> From: Suketu Shah <suketu.j.shah@intel.com>
> 
> Add triggers as per expectations mentioned in gen9_enable_dc5
> and gen9_disable_dc5 patch.
> 
> Also call POSTING_READ for every write to a register to ensure that
> its written immediately.
> 
> v1: Remove POSTING_READ calls as they've already been added in previous patches.
> 
> v2: Rebase to move all runtime pm specific changes to intel_runtime_pm.c file.
> 
> Modified as per review comments from Imre:
> 1] Change variable name 'dc5_allowed' to 'dc5_enabled' to correspond to relevant
>    functions.
> 2] Move the check dc5_enabled in skl_set_power_well() to disable DC5 into
>    gen9_disable_DC5 which is a more appropriate place.
> 3] Convert checks for 'pm.dc5_enabled' and 'pm.suspended' in skl_set_power_well()
>    to warnings. However, removing them for now as they'll be included in a future patch
>    asserting DC-state entry/exit criteria.
> 4] Enable DC5, only when CSR firmware is verified to be loaded. Create new structure
>    to track 'enabled' and 'deferred' status of DC5.
> 5] Ensure runtime PM reference is obtained, if CSR is not loaded, to avoid entering
>    runtime-suspend and release it when it's loaded.
> 6] Protect necessary CSR-related code with locks.
> 7] Move CSR-loading call to runtime PM initialization, as power domains needed to be
>    accessed during deferred DC5-enabling, are not initialized earlier.
> 
> v3: Rebase to latest.
> 
> Modified as per review comments from Imre:
> 1] Use blocking wait for CSR-loading to finish to enable DC5  for simplicity, instead of
>    deferring enabling DC5 until CSR is loaded.
> 2] Obtain runtime PM reference during CSR-loading initialization itself as deferred DC5-
>    enabling is removed and release it at the end of CSR-loading functionality.
> 3] Revert calling CSR-loading functionality to the beginning of i915 driver-load
>    functionality to avoid any delay in loading.
> 4] Define another variable to track whether CSR-loading failed and use it to avoid enabling
>    DC5 if it's true.
> 5] Define CSR-load-status accessor functions for use later.
> 
> v4:
> 1] Disable DC5 before enabling PG2 instead of after it.
> 2] DC5 was being mistaken enabled even when CSR-loading timed-out. Fix that.
> 3] Enable DC5-related functionality using a macro.
> 4] Remove dc5_enabled tracking variable and its use as it's not needed now.
> 
> v5:
> 1] Mark CSR failed to load where necessary in finish_csr_load function.
> 2] Use mutex-protected accessor function to check if CSR loaded instead of directly
>    accessing the variable.
> 3] Prefix csr_load_status_get/set function names with intel_.
> 
> v6: rebase to latest.
> v7: Rebase on top of nightly (Damien)
> v8: Squashed the patch from Imre - added csr helper pointers to simplify the code. (Imre)
> v9: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)
> v10: Added a enum for different csr states, suggested by Imre. (Animesh)
> 
> v11: Based on review comments from Imre, Damien and Daniel following changes done
> - enum name chnaged to csr_state (singular form).
> - FW_UNINITIALIZED used as zeroth element in enum csr_state.
> - Prototype changed for helper function(set/get csr status), using enum csr_state instead of bool.
> 
> Issue: VIZ-2819
> Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com>
> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h         |  7 +++++
>  drivers/gpu/drm/i915/intel_csr.c        | 49 +++++++++++++++++++++++++++++++--
>  drivers/gpu/drm/i915/intel_drv.h        |  3 ++
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 33 ++++++++++++++++++++++
>  4 files changed, 90 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 90e47a9..670e407 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -667,6 +667,12 @@ struct intel_uncore {
>  #define for_each_fw_domain(domain__, dev_priv__, i__) \
>  	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
>  
> +enum csr_state {
> +	FW_UNINITIALIZED = 0,
> +	FW_LOADED,
> +	FW_FAILED
> +};
> +
>  struct intel_csr {
>  	const char *fw_path;
>  	__be32 *dmc_payload;
> @@ -674,6 +680,7 @@ struct intel_csr {
>  	uint32_t mmio_count;
>  	uint32_t mmioaddr[8];
>  	uint32_t mmiodata[8];
> +	enum csr_state state;
>  };
>  
>  #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
> diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
> index f5fa574..fe6789f 100644
> --- a/drivers/gpu/drm/i915/intel_csr.c
> +++ b/drivers/gpu/drm/i915/intel_csr.c
> @@ -183,6 +183,25 @@ static char intel_get_substepping(struct drm_device *dev)
>  		return -ENODATA;
>  }
>  
> +enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv)
> +{
> +	enum csr_state state;
> +
> +	mutex_lock(&dev_priv->csr_lock);
> +	state = dev_priv->csr.state;
> +	mutex_unlock(&dev_priv->csr_lock);
> +
> +	return state;
> +}
> +
> +void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
> +			enum csr_state state)
> +{
> +	mutex_lock(&dev_priv->csr_lock);
> +	dev_priv->csr.state = state;
> +	mutex_unlock(&dev_priv->csr_lock);
> +}
> +
>  void intel_csr_load_program(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -204,6 +223,8 @@ void intel_csr_load_program(struct drm_device *dev)
>  		I915_WRITE(dev_priv->csr.mmioaddr[i],
>  			dev_priv->csr.mmiodata[i]);
>  	}
> +
> +	dev_priv->csr.state = FW_LOADED;
>  	mutex_unlock(&dev_priv->csr_lock);
>  }
>  
> @@ -223,11 +244,13 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  
>  	if (!fw) {
>  		i915_firmware_load_error_print(csr->fw_path, 0);
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>  		goto out;
>  	}
>  
>  	if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
>  		DRM_ERROR("Unknown stepping info, firmware loading failed\n");
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>  		goto out;
>  	}
>  
> @@ -237,6 +260,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  		(css_header->header_len * 4)) {
>  		DRM_ERROR("Firmware has wrong CSS header length %u bytes\n",
>  			(css_header->header_len * 4));
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>  		goto out;
>  	}
>  	readcount += sizeof(struct intel_css_header);
> @@ -248,6 +272,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  		(package_header->header_len * 4)) {
>  		DRM_ERROR("Firmware has wrong package header length %u bytes\n",
>  			(package_header->header_len * 4));
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>  		goto out;
>  	}
>  	readcount += sizeof(struct intel_package_header);
> @@ -268,6 +293,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  	}
>  	if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
>  		DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>  		goto out;
>  	}
>  	readcount += dmc_offset;
> @@ -277,6 +303,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  	if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) {
>  		DRM_ERROR("Firmware has wrong dmc header length %u bytes\n",
>  				(dmc_header->header_len));
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>  		goto out;
>  	}
>  	readcount += sizeof(struct intel_dmc_header);
> @@ -285,6 +312,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  	if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) {
>  		DRM_ERROR("Firmware has wrong mmio count %u\n",
>  						dmc_header->mmio_count);
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>  		goto out;
>  	}
>  	csr->mmio_count = dmc_header->mmio_count;
> @@ -293,6 +321,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  			dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
>  			DRM_ERROR(" Firmware has wrong mmio address 0x%x\n",
>  						dmc_header->mmioaddr[i]);
> +			intel_csr_load_status_set(dev_priv, FW_FAILED);
>  			goto out;
>  		}
>  		csr->mmioaddr[i] = dmc_header->mmioaddr[i];
> @@ -303,6 +332,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  	nbytes = dmc_header->fw_size * 4;
>  	if (nbytes > CSR_MAX_FW_SIZE) {
>  		DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes);
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>  		goto out;
>  	}
>  	csr->dmc_fw_size = dmc_header->fw_size;
> @@ -310,6 +340,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  	csr->dmc_payload = kmalloc(nbytes, GFP_KERNEL);
>  	if (!csr->dmc_payload) {
>  		DRM_ERROR("Memory allocation failed for dmc payload\n");
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>  		goto out;
>  	}
>  
> @@ -327,6 +358,11 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  	/* load csr program during system boot, as needed for DC states */
>  	intel_csr_load_program(dev);
>  out:
> +	/*
> +	 * Release the runtime pm reference obtained when
> +	 * CSR wasn't loaded.
> +	 */
> +	intel_runtime_pm_put(dev_priv);

I'm not sure if runtime PM would work correctly without DC5/6, so let's
not enable RPM if the firmware fails to load. This is also inconsistent
with the error handling in intel_csr_ucode_init().

>  	release_firmware(fw);
>  }
>  
> @@ -343,17 +379,25 @@ void intel_csr_ucode_init(struct drm_device *dev)
>  		csr->fw_path = I915_CSR_SKL;
>  	else {
>  		DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>  		return;
>  	}
>  
> +	/*
> +	 * Obtain a runtime pm reference, until CSR is loaded,
> +	 * to avoid entering runtime-suspend.
> +	 */
> +	intel_runtime_pm_get(dev_priv);
> +
>  	/* CSR supported for platform, load firmware */
>  	ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path,
>  				&dev_priv->dev->pdev->dev,
>  				GFP_KERNEL, dev_priv,
>  				finish_csr_load);
> -	if (ret)
> +	if (ret) {
>  		i915_firmware_load_error_print(csr->fw_path, ret);
> -
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> +	}
>  }
>  
>  void intel_csr_ucode_fini(struct drm_device *dev)
> @@ -363,5 +407,6 @@ void intel_csr_ucode_fini(struct drm_device *dev)
>  	if (!HAS_CSR(dev))
>  		return;
>  
> +	intel_csr_load_status_set(dev_priv, FW_FAILED);
>  	kfree(dev_priv->csr.dmc_payload);
>  }
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index f3a2d88..25d7956 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1064,6 +1064,9 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
>  
>  /* intel_csr.c */
>  void intel_csr_ucode_init(struct drm_device *dev);
> +enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv);
> +void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
> +					enum csr_state state);
>  void intel_csr_load_program(struct drm_device *dev);
>  void intel_csr_ucode_fini(struct drm_device *dev);
>  
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index ce00e69..23f02a8 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -49,6 +49,8 @@
>   * present for a given platform.
>   */
>  
> +#define GEN9_ENABLE_DC5(dev) (IS_SKYLAKE(dev))
> +
>  #define for_each_power_well(i, power_well, domain_mask, power_domains)	\
>  	for (i = 0;							\
>  	     i < (power_domains)->power_well_count &&			\
> @@ -319,9 +321,20 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
>  	SKL_DISPLAY_MISC_IO_POWER_DOMAINS)) |		\
>  	BIT(POWER_DOMAIN_INIT))
>  
> +static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
> +{
> +	/* TODO: Implementation to be done. */
> +}
> +
> +static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
> +{
> +	/* TODO: Implementation to be done. */
> +}
> +
>  static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  			struct i915_power_well *power_well, bool enable)
>  {
> +	struct drm_device *dev = dev_priv->dev;
>  	uint32_t tmp, fuse_status;
>  	uint32_t req_mask, state_mask;
>  	bool is_enabled, enable_requested, check_fuse_status = false;
> @@ -361,6 +374,13 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  
>  	if (enable) {
>  		if (!enable_requested) {
> +			WARN((tmp & state_mask) &&
> +				!I915_READ(HSW_PWR_WELL_BIOS),
> +				"Invalid for power well status to be enabled, unless done by the BIOS, \
> +				when request is to disable!\n");
> +			if (GEN9_ENABLE_DC5(dev) &&
> +				power_well->data == SKL_DISP_PW_2)
> +				gen9_disable_dc5(dev_priv);
>  			I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask);
>  		}
>  
> @@ -377,6 +397,19 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  			I915_WRITE(HSW_PWR_WELL_DRIVER,	tmp & ~req_mask);
>  			POSTING_READ(HSW_PWR_WELL_DRIVER);
>  			DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
> +
> +			if (GEN9_ENABLE_DC5(dev) &&
> +				power_well->data == SKL_DISP_PW_2) {
> +				enum csr_state state;
> +
> +				wait_for((state = intel_csr_load_status_get(dev_priv)) !=
> +						FW_UNINITIALIZED, 1000);
> +				if (state != FW_LOADED)
> +					DRM_ERROR("CSR firmware not ready (%d)\n",
> +							state);
> +				else
> +					gen9_enable_dc5(dev_priv);
> +			}
>  		}
>  	}
>  


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

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

* Re: [PATCH v4 2/8] drm/i915/skl: Add DC5 Trigger Sequence.
  2015-04-16  9:25   ` Imre Deak
@ 2015-04-16  9:48     ` Imre Deak
  2015-04-17  5:59       ` Animesh Manna
  0 siblings, 1 reply; 37+ messages in thread
From: Imre Deak @ 2015-04-16  9:48 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On to, 2015-04-16 at 12:25 +0300, Imre Deak wrote:
> On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
> >  [...]
> > @@ -223,11 +244,13 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >  
> >  	if (!fw) {
> >  		i915_firmware_load_error_print(csr->fw_path, 0);
> > +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >  		goto out;
> >  	}
> >  
> >  	if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
> >  		DRM_ERROR("Unknown stepping info, firmware loading failed\n");
> > +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >  		goto out;
> >  	}
> >  
> > @@ -237,6 +260,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >  		(css_header->header_len * 4)) {
> >  		DRM_ERROR("Firmware has wrong CSS header length %u bytes\n",
> >  			(css_header->header_len * 4));
> > +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >  		goto out;
> >  	}
> >  	readcount += sizeof(struct intel_css_header);
> > @@ -248,6 +272,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >  		(package_header->header_len * 4)) {
> >  		DRM_ERROR("Firmware has wrong package header length %u bytes\n",
> >  			(package_header->header_len * 4));
> > +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >  		goto out;
> >  	}
> >  	readcount += sizeof(struct intel_package_header);
> > @@ -268,6 +293,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >  	}
> >  	if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
> >  		DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
> > +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >  		goto out;
> >  	}
> >  	readcount += dmc_offset;
> > @@ -277,6 +303,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >  	if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) {
> >  		DRM_ERROR("Firmware has wrong dmc header length %u bytes\n",
> >  				(dmc_header->header_len));
> > +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >  		goto out;
> >  	}
> >  	readcount += sizeof(struct intel_dmc_header);
> > @@ -285,6 +312,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >  	if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) {
> >  		DRM_ERROR("Firmware has wrong mmio count %u\n",
> >  						dmc_header->mmio_count);
> > +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >  		goto out;
> >  	}
> >  	csr->mmio_count = dmc_header->mmio_count;
> > @@ -293,6 +321,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >  			dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
> >  			DRM_ERROR(" Firmware has wrong mmio address 0x%x\n",
> >  						dmc_header->mmioaddr[i]);
> > +			intel_csr_load_status_set(dev_priv, FW_FAILED);
> >  			goto out;
> >  		}
> >  		csr->mmioaddr[i] = dmc_header->mmioaddr[i];
> > @@ -303,6 +332,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >  	nbytes = dmc_header->fw_size * 4;
> >  	if (nbytes > CSR_MAX_FW_SIZE) {
> >  		DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes);
> > +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >  		goto out;
> >  	}
> >  	csr->dmc_fw_size = dmc_header->fw_size;
> > @@ -310,6 +340,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >  	csr->dmc_payload = kmalloc(nbytes, GFP_KERNEL);
> >  	if (!csr->dmc_payload) {
> >  		DRM_ERROR("Memory allocation failed for dmc payload\n");
> > +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >  		goto out;
> >  	}
> >  
> > @@ -327,6 +358,11 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >  	/* load csr program during system boot, as needed for DC states */
> >  	intel_csr_load_program(dev);
> >  out:

Also, since you have to anyway change the patch: could you replace all
the above intel_csr_load_status_set(dev_priv, FW_FAILED); with one here
using a fw_loaded bool that you set after intel_csr_load_program?

> > +	/*
> > +	 * Release the runtime pm reference obtained when
> > +	 * CSR wasn't loaded.
> > +	 */
> > +	intel_runtime_pm_put(dev_priv);


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

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

* Re: [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware.
  2015-04-16 11:59     ` Animesh Manna
@ 2015-04-16 11:25       ` Imre Deak
  2015-04-16 14:23         ` Animesh Manna
  0 siblings, 1 reply; 37+ messages in thread
From: Imre Deak @ 2015-04-16 11:25 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx

On to, 2015-04-16 at 17:29 +0530, Animesh Manna wrote:
> + Jesse, Rodrigo
> 
> On 04/16/2015 02:51 PM, Imre Deak wrote:
> > On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
> >> [...]
> >> +#include <linux/firmware.h>
> >> +#include "i915_drv.h"
> >> +#include "i915_reg.h"
> >> +
> >> +#define I915_CSR_SKL "i915/skl_dmc_ver1.bin"
> > The latest version on the FW download page is skl_dmc_ver4.bin as Damien
> > pointed out and skl_dmc_ver1.bin is not available there. So why did you
> > choose ver1? If ver4 is not compatible with the current driver code,
> > then ver1 must be made available too on the download page, otherwise we
> > should use here ver4.
> >
> > The patch otherwise looks ok to me.
> >
> > --Imre
>
> Yes, 01.org will be updated with skl_dmc_ver1.bin. Thinking of  future
> scaling it is decided that we will follow the naming convention
> <platform>_dmc_<api-version>.bin and this will be a symbolic link of
> the actual firmware.
>
> Will be requesting firmware team to release firmware in
> <platform>_dmc_<api-version>_<minor-version>.bin Here in
> skl_dmc_ver4.bin api version is 1.0 and minor version is 4, so changed
> the file name to skl_dmc_ver1.bin.

I just repeat here Damien, but I don't think there is a need to
complicate things with symlinks. IMO I915_CSR_SKL should point to the
exact version of the firmware, not just to a symlink with the API
version. The driver will be tested with that particular firmware version
and so the driver writers should be in full control of what version will
be loaded with a given driver version.

--Imre

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

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

* Re: [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware.
  2015-04-16  9:21   ` Imre Deak
@ 2015-04-16 11:59     ` Animesh Manna
  2015-04-16 11:25       ` Imre Deak
  0 siblings, 1 reply; 37+ messages in thread
From: Animesh Manna @ 2015-04-16 11:59 UTC (permalink / raw)
  To: imre.deak; +Cc: intel-gfx

+ Jesse, Rodrigo

On 04/16/2015 02:51 PM, Imre Deak wrote:
> On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
>> [...]
>> +#include <linux/firmware.h>
>> +#include "i915_drv.h"
>> +#include "i915_reg.h"
>> +
>> +#define I915_CSR_SKL "i915/skl_dmc_ver1.bin"
> The latest version on the FW download page is skl_dmc_ver4.bin as Damien
> pointed out and skl_dmc_ver1.bin is not available there. So why did you
> choose ver1? If ver4 is not compatible with the current driver code,
> then ver1 must be made available too on the download page, otherwise we
> should use here ver4.
>
> The patch otherwise looks ok to me.
>
> --Imre
>
Yes, 01.org will be updated with skl_dmc_ver1.bin. Thinking of  future scaling it is decided that we will follow the naming convention
<platform>_dmc_<api-version>.bin and this will be a symbolic link of the actual firmware.

Will be requesting firmware team to release firmware in <platform>_dmc_<api-version>_<minor-version>.bin
Here in skl_dmc_ver4.bin api version is 1.0 and minor version is 4, so changed the file name to skl_dmc_ver1.bin.

Regards,
Animesh

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

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

* Re: [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware.
  2015-04-16 11:25       ` Imre Deak
@ 2015-04-16 14:23         ` Animesh Manna
  2015-04-16 15:20           ` Imre Deak
  0 siblings, 1 reply; 37+ messages in thread
From: Animesh Manna @ 2015-04-16 14:23 UTC (permalink / raw)
  To: imre.deak, jesse.barnes; +Cc: tarak.p.shah, intel-gfx, rodrigo.vivi



On 4/16/2015 4:55 PM, Imre Deak wrote:
> On to, 2015-04-16 at 17:29 +0530, Animesh Manna wrote:
>> + Jesse, Rodrigo
>>
>> On 04/16/2015 02:51 PM, Imre Deak wrote:
>>> On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
>>>> [...]
>>>> +#include <linux/firmware.h>
>>>> +#include "i915_drv.h"
>>>> +#include "i915_reg.h"
>>>> +
>>>> +#define I915_CSR_SKL "i915/skl_dmc_ver1.bin"
>>> The latest version on the FW download page is skl_dmc_ver4.bin as Damien
>>> pointed out and skl_dmc_ver1.bin is not available there. So why did you
>>> choose ver1? If ver4 is not compatible with the current driver code,
>>> then ver1 must be made available too on the download page, otherwise we
>>> should use here ver4.
>>>
>>> The patch otherwise looks ok to me.
>>>
>>> --Imre
>> Yes, 01.org will be updated with skl_dmc_ver1.bin. Thinking of  future
>> scaling it is decided that we will follow the naming convention
>> <platform>_dmc_<api-version>.bin and this will be a symbolic link of
>> the actual firmware.
>>
>> Will be requesting firmware team to release firmware in
>> <platform>_dmc_<api-version>_<minor-version>.bin Here in
>> skl_dmc_ver4.bin api version is 1.0 and minor version is 4, so changed
>> the file name to skl_dmc_ver1.bin.
> I just repeat here Damien, but I don't think there is a need to
> complicate things with symlinks. IMO I915_CSR_SKL should point to the
> exact version of the firmware, not just to a symlink with the API
> version. The driver will be tested with that particular firmware version
> and so the driver writers should be in full control of what version will
> be loaded with a given driver version.
>
> --Imre

Hi Imre,

Agree, if we want to support only latest firmware for a particular platform we do not need symlink
but during discussion found that if user want to rollback the newest firmware for same API version
which can be achievable by using symlink and introducing api-version and minor-version. Anyways I am
ok with both the approaches.

Adding Jessi also,

Please suggest to proceed further.

Regards,
Animesh

>

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

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

* Re: [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware.
  2015-04-16 14:23         ` Animesh Manna
@ 2015-04-16 15:20           ` Imre Deak
  0 siblings, 0 replies; 37+ messages in thread
From: Imre Deak @ 2015-04-16 15:20 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx, jesse.barnes, rodrigo.vivi, tarak.p.shah

On Thu, 2015-04-16 at 19:53 +0530, Animesh Manna wrote:
> 
> On 4/16/2015 4:55 PM, Imre Deak wrote:
> > On to, 2015-04-16 at 17:29 +0530, Animesh Manna wrote:
> >> + Jesse, Rodrigo
> >>
> >> On 04/16/2015 02:51 PM, Imre Deak wrote:
> >>> On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
> >>>> [...]
> >>>> +#include <linux/firmware.h>
> >>>> +#include "i915_drv.h"
> >>>> +#include "i915_reg.h"
> >>>> +
> >>>> +#define I915_CSR_SKL "i915/skl_dmc_ver1.bin"
> >>> The latest version on the FW download page is skl_dmc_ver4.bin as Damien
> >>> pointed out and skl_dmc_ver1.bin is not available there. So why did you
> >>> choose ver1? If ver4 is not compatible with the current driver code,
> >>> then ver1 must be made available too on the download page, otherwise we
> >>> should use here ver4.
> >>>
> >>> The patch otherwise looks ok to me.
> >>>
> >>> --Imre
> >> Yes, 01.org will be updated with skl_dmc_ver1.bin. Thinking of  future
> >> scaling it is decided that we will follow the naming convention
> >> <platform>_dmc_<api-version>.bin and this will be a symbolic link of
> >> the actual firmware.
> >>
> >> Will be requesting firmware team to release firmware in
> >> <platform>_dmc_<api-version>_<minor-version>.bin Here in
> >> skl_dmc_ver4.bin api version is 1.0 and minor version is 4, so changed
> >> the file name to skl_dmc_ver1.bin.
> > I just repeat here Damien, but I don't think there is a need to
> > complicate things with symlinks. IMO I915_CSR_SKL should point to the
> > exact version of the firmware, not just to a symlink with the API
> > version. The driver will be tested with that particular firmware version
> > and so the driver writers should be in full control of what version will
> > be loaded with a given driver version.
>
> Agree, if we want to support only latest firmware for a particular
> platform we do not need symlink but during discussion found that if
> user want to rollback the newest firmware for same API version which
> can be achievable by using symlink and introducing api-version and
> minor-version. Anyways I am ok with both the approaches.

The only reason I can see for rolling back would be a regression. Fixing
that would need to go through the usual bug reporting flow and eventual
firmware and driver update. A symlink could anyway be created - as a
kind of hack - to force loading a different firmware version, but making
this the regular way would only allow for confusion about which firmware
version is actually loaded.

--Imre

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

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

* Re: [PATCH v4 8/8] drm/i915/skl: Enable runtime PM
  2015-04-16  8:52 ` [PATCH v4 8/8] drm/i915/skl: Enable runtime PM Animesh Manna
@ 2015-04-17  1:52   ` shuang.he
  2015-04-30 13:47   ` Imre Deak
  1 sibling, 0 replies; 37+ messages in thread
From: shuang.he @ 2015-04-17  1:52 UTC (permalink / raw)
  To: shuang.he, ethan.gao, intel-gfx, animesh.manna

Tested-By: Intel Graphics QA PRTS (Patch Regression Test System Contact: shuang.he@intel.com)
Task id: 6212
-------------------------------------Summary-------------------------------------
Platform          Delta          drm-intel-nightly          Series Applied
PNV                                  276/276              276/276
ILK                                  302/302              302/302
SNB                                  318/318              318/318
IVB                                  341/341              341/341
BYT                                  287/287              287/287
HSW                 -1              395/395              394/395
BDW                                  318/318              318/318
-------------------------------------Detailed-------------------------------------
Platform  Test                                drm-intel-nightly          Series Applied
 HSW  igt@gem_pwrite_pread@snooped-pwrite-blt-cpu_mmap-performance      DMESG_WARN(1)PASS(7)      DMESG_WARN(1)PASS(1)
(dmesg patch applied)drm:i915_hangcheck_elapsed[i915]]*ERROR*Hangcheck_timer_elapsed...blitter_ring_idle@Hangcheck timer elapsed... blitter ring idle
Note: You need to pay more attention to line start with '*'
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v4 2/8] drm/i915/skl: Add DC5 Trigger Sequence.
  2015-04-16  9:48     ` Imre Deak
@ 2015-04-17  5:59       ` Animesh Manna
  2015-04-17  7:15         ` Imre Deak
  0 siblings, 1 reply; 37+ messages in thread
From: Animesh Manna @ 2015-04-17  5:59 UTC (permalink / raw)
  To: imre.deak; +Cc: Suketu Shah, intel-gfx



On 4/16/2015 3:18 PM, Imre Deak wrote:
> On to, 2015-04-16 at 12:25 +0300, Imre Deak wrote:
>> On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
>>>   [...]
>>> @@ -223,11 +244,13 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>>>   
>>>   	if (!fw) {
>>>   		i915_firmware_load_error_print(csr->fw_path, 0);
>>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>>>   		goto out;
>>>   	}
>>>   
>>>   	if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
>>>   		DRM_ERROR("Unknown stepping info, firmware loading failed\n");
>>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>>>   		goto out;
>>>   	}
>>>   
>>> @@ -237,6 +260,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>>>   		(css_header->header_len * 4)) {
>>>   		DRM_ERROR("Firmware has wrong CSS header length %u bytes\n",
>>>   			(css_header->header_len * 4));
>>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>>>   		goto out;
>>>   	}
>>>   	readcount += sizeof(struct intel_css_header);
>>> @@ -248,6 +272,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>>>   		(package_header->header_len * 4)) {
>>>   		DRM_ERROR("Firmware has wrong package header length %u bytes\n",
>>>   			(package_header->header_len * 4));
>>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>>>   		goto out;
>>>   	}
>>>   	readcount += sizeof(struct intel_package_header);
>>> @@ -268,6 +293,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>>>   	}
>>>   	if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
>>>   		DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
>>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>>>   		goto out;
>>>   	}
>>>   	readcount += dmc_offset;
>>> @@ -277,6 +303,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>>>   	if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) {
>>>   		DRM_ERROR("Firmware has wrong dmc header length %u bytes\n",
>>>   				(dmc_header->header_len));
>>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>>>   		goto out;
>>>   	}
>>>   	readcount += sizeof(struct intel_dmc_header);
>>> @@ -285,6 +312,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>>>   	if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) {
>>>   		DRM_ERROR("Firmware has wrong mmio count %u\n",
>>>   						dmc_header->mmio_count);
>>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>>>   		goto out;
>>>   	}
>>>   	csr->mmio_count = dmc_header->mmio_count;
>>> @@ -293,6 +321,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>>>   			dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
>>>   			DRM_ERROR(" Firmware has wrong mmio address 0x%x\n",
>>>   						dmc_header->mmioaddr[i]);
>>> +			intel_csr_load_status_set(dev_priv, FW_FAILED);
>>>   			goto out;
>>>   		}
>>>   		csr->mmioaddr[i] = dmc_header->mmioaddr[i];
>>> @@ -303,6 +332,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>>>   	nbytes = dmc_header->fw_size * 4;
>>>   	if (nbytes > CSR_MAX_FW_SIZE) {
>>>   		DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes);
>>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>>>   		goto out;
>>>   	}
>>>   	csr->dmc_fw_size = dmc_header->fw_size;
>>> @@ -310,6 +340,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>>>   	csr->dmc_payload = kmalloc(nbytes, GFP_KERNEL);
>>>   	if (!csr->dmc_payload) {
>>>   		DRM_ERROR("Memory allocation failed for dmc payload\n");
>>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>>>   		goto out;
>>>   	}
>>>   
>>> @@ -327,6 +358,11 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>>>   	/* load csr program during system boot, as needed for DC states */
>>>   	intel_csr_load_program(dev);
>>>   out:
> Also, since you have to anyway change the patch: could you replace all
> the above intel_csr_load_status_set(dev_priv, FW_FAILED); with one here
> using a fw_loaded bool that you set after intel_csr_load_program?

Now we do not have fw_loaded bool in current patch, enum csr_state is used to capture the current state.
Want me to add fw_loaded bool and call intel_csr_load_status_set(dev_priv, FW_FAILED) based on that?

Regards,
Animesh

>
>>> +	/*
>>> +	 * Release the runtime pm reference obtained when
>>> +	 * CSR wasn't loaded.
>>> +	 */
>>> +	intel_runtime_pm_put(dev_priv);
>

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

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

* Re: [PATCH v4 2/8] drm/i915/skl: Add DC5 Trigger Sequence.
  2015-04-17  5:59       ` Animesh Manna
@ 2015-04-17  7:15         ` Imre Deak
  2015-04-17 14:16           ` [PATCH v5 2/2] " Animesh Manna
  0 siblings, 1 reply; 37+ messages in thread
From: Imre Deak @ 2015-04-17  7:15 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On Fri, 2015-04-17 at 11:29 +0530, Animesh Manna wrote:
> 
> On 4/16/2015 3:18 PM, Imre Deak wrote:
> > On to, 2015-04-16 at 12:25 +0300, Imre Deak wrote:
> >> On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
> >>>   [...]
> >>> @@ -223,11 +244,13 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >>>   

To clarify, I meant to add at the top of this function:
bool fw_loaded = false;

> >>>   	if (!fw) {
> >>>   		i915_firmware_load_error_print(csr->fw_path, 0);
> >>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);

... remove all the intel_csr_load_status_set(FW_FAILED) calls added in
this function

> >>>   		goto out;
> >>>   	}
> >>>   
> >>>   	if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
> >>>   		DRM_ERROR("Unknown stepping info, firmware loading failed\n");
> >>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >>>   		goto out;
> >>>   	}
> >>>   
> >>> @@ -237,6 +260,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >>>   		(css_header->header_len * 4)) {
> >>>   		DRM_ERROR("Firmware has wrong CSS header length %u bytes\n",
> >>>   			(css_header->header_len * 4));
> >>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >>>   		goto out;
> >>>   	}
> >>>   	readcount += sizeof(struct intel_css_header);
> >>> @@ -248,6 +272,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >>>   		(package_header->header_len * 4)) {
> >>>   		DRM_ERROR("Firmware has wrong package header length %u bytes\n",
> >>>   			(package_header->header_len * 4));
> >>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >>>   		goto out;
> >>>   	}
> >>>   	readcount += sizeof(struct intel_package_header);
> >>> @@ -268,6 +293,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >>>   	}
> >>>   	if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
> >>>   		DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
> >>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >>>   		goto out;
> >>>   	}
> >>>   	readcount += dmc_offset;
> >>> @@ -277,6 +303,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >>>   	if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) {
> >>>   		DRM_ERROR("Firmware has wrong dmc header length %u bytes\n",
> >>>   				(dmc_header->header_len));
> >>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >>>   		goto out;
> >>>   	}
> >>>   	readcount += sizeof(struct intel_dmc_header);
> >>> @@ -285,6 +312,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >>>   	if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) {
> >>>   		DRM_ERROR("Firmware has wrong mmio count %u\n",
> >>>   						dmc_header->mmio_count);
> >>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >>>   		goto out;
> >>>   	}
> >>>   	csr->mmio_count = dmc_header->mmio_count;
> >>> @@ -293,6 +321,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >>>   			dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
> >>>   			DRM_ERROR(" Firmware has wrong mmio address 0x%x\n",
> >>>   						dmc_header->mmioaddr[i]);
> >>> +			intel_csr_load_status_set(dev_priv, FW_FAILED);
> >>>   			goto out;
> >>>   		}
> >>>   		csr->mmioaddr[i] = dmc_header->mmioaddr[i];
> >>> @@ -303,6 +332,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >>>   	nbytes = dmc_header->fw_size * 4;
> >>>   	if (nbytes > CSR_MAX_FW_SIZE) {
> >>>   		DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes);
> >>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >>>   		goto out;
> >>>   	}
> >>>   	csr->dmc_fw_size = dmc_header->fw_size;
> >>> @@ -310,6 +340,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >>>   	csr->dmc_payload = kmalloc(nbytes, GFP_KERNEL);
> >>>   	if (!csr->dmc_payload) {
> >>>   		DRM_ERROR("Memory allocation failed for dmc payload\n");
> >>> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> >>>   		goto out;
> >>>   	}
> >>>   
> >>> @@ -327,6 +358,11 @@ static void finish_csr_load(const struct firmware *fw, void *context)
> >>>   	/* load csr program during system boot, as needed for DC states */
> >>>   	intel_csr_load_program(dev);

... set fw_loaded = true; here

> >>>   out:
> > Also, since you have to anyway change the patch: could you replace all
> > the above intel_csr_load_status_set(dev_priv, FW_FAILED); with one here
> > using a fw_loaded bool that you set after intel_csr_load_program?
>
> Now we do not have fw_loaded bool in current patch, enum csr_state is
> used to capture the current state. Want me to add fw_loaded bool and
> call intel_csr_load_status_set(dev_priv, FW_FAILED) based on that?

... and add here
if (!fw_loaded)
	intel_csr_load_status_set(dev_priv, FW_FAILED);

to remove some duplication in the code.

--Imre


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

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

* [PATCH v5 2/2] drm/i915/skl: Add DC5 Trigger Sequence
  2015-04-17  7:15         ` Imre Deak
@ 2015-04-17 14:16           ` Animesh Manna
  2015-04-30 13:18             ` Imre Deak
  2015-05-04  9:39             ` Daniel Vetter
  0 siblings, 2 replies; 37+ messages in thread
From: Animesh Manna @ 2015-04-17 14:16 UTC (permalink / raw)
  To: intel-gfx; +Cc: Suketu Shah

From: Suketu Shah <suketu.j.shah@intel.com>

Add triggers as per expectations mentioned in gen9_enable_dc5
and gen9_disable_dc5 patch.

Also call POSTING_READ for every write to a register to ensure that
its written immediately.

v1: Remove POSTING_READ calls as they've already been added in previous patches.

v2: Rebase to move all runtime pm specific changes to intel_runtime_pm.c file.

Modified as per review comments from Imre:
1] Change variable name 'dc5_allowed' to 'dc5_enabled' to correspond to relevant
   functions.
2] Move the check dc5_enabled in skl_set_power_well() to disable DC5 into
   gen9_disable_DC5 which is a more appropriate place.
3] Convert checks for 'pm.dc5_enabled' and 'pm.suspended' in skl_set_power_well()
   to warnings. However, removing them for now as they'll be included in a future patch
   asserting DC-state entry/exit criteria.
4] Enable DC5, only when CSR firmware is verified to be loaded. Create new structure
   to track 'enabled' and 'deferred' status of DC5.
5] Ensure runtime PM reference is obtained, if CSR is not loaded, to avoid entering
   runtime-suspend and release it when it's loaded.
6] Protect necessary CSR-related code with locks.
7] Move CSR-loading call to runtime PM initialization, as power domains needed to be
   accessed during deferred DC5-enabling, are not initialized earlier.

v3: Rebase to latest.

Modified as per review comments from Imre:
1] Use blocking wait for CSR-loading to finish to enable DC5  for simplicity, instead of
   deferring enabling DC5 until CSR is loaded.
2] Obtain runtime PM reference during CSR-loading initialization itself as deferred DC5-
   enabling is removed and release it at the end of CSR-loading functionality.
3] Revert calling CSR-loading functionality to the beginning of i915 driver-load
   functionality to avoid any delay in loading.
4] Define another variable to track whether CSR-loading failed and use it to avoid enabling
   DC5 if it's true.
5] Define CSR-load-status accessor functions for use later.

v4:
1] Disable DC5 before enabling PG2 instead of after it.
2] DC5 was being mistaken enabled even when CSR-loading timed-out. Fix that.
3] Enable DC5-related functionality using a macro.
4] Remove dc5_enabled tracking variable and its use as it's not needed now.

v5:
1] Mark CSR failed to load where necessary in finish_csr_load function.
2] Use mutex-protected accessor function to check if CSR loaded instead of directly
   accessing the variable.
3] Prefix csr_load_status_get/set function names with intel_.

v6: rebase to latest.
v7: Rebase on top of nightly (Damien)
v8: Squashed the patch from Imre - added csr helper pointers to simplify the code. (Imre)
v9: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)
v10: Added a enum for different csr states, suggested by Imre. (Animesh)

v11: Based on review comments from Imre, Damien and Daniel following changes done
- enum name chnaged to csr_state (singular form).
- FW_UNINITIALIZED used as zeroth element in enum csr_state.
- Prototype changed for helper function(set/get csr status), using enum csr_state instead of bool.

v12: Based on review comment from Imre, introduced bool fw_loaded local to finish_csr_load() which helps
calling once to set the csr status. The same flag used to fail RPM if find any issue during
firmware loading.

Issue: VIZ-2819
Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
Signed-off-by: Suketu Shah <suketu.j.shah@intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h         |  7 ++++++
 drivers/gpu/drm/i915/intel_csr.c        | 42 +++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_drv.h        |  3 +++
 drivers/gpu/drm/i915/intel_runtime_pm.c | 33 ++++++++++++++++++++++++++
 4 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 90e47a9..670e407 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -667,6 +667,12 @@ struct intel_uncore {
 #define for_each_fw_domain(domain__, dev_priv__, i__) \
 	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
 
+enum csr_state {
+	FW_UNINITIALIZED = 0,
+	FW_LOADED,
+	FW_FAILED
+};
+
 struct intel_csr {
 	const char *fw_path;
 	__be32 *dmc_payload;
@@ -674,6 +680,7 @@ struct intel_csr {
 	uint32_t mmio_count;
 	uint32_t mmioaddr[8];
 	uint32_t mmiodata[8];
+	enum csr_state state;
 };
 
 #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
index f5fa574..3bd29b5 100644
--- a/drivers/gpu/drm/i915/intel_csr.c
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -183,6 +183,25 @@ static char intel_get_substepping(struct drm_device *dev)
 		return -ENODATA;
 }
 
+enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv)
+{
+	enum csr_state state;
+
+	mutex_lock(&dev_priv->csr_lock);
+	state = dev_priv->csr.state;
+	mutex_unlock(&dev_priv->csr_lock);
+
+	return state;
+}
+
+void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
+			enum csr_state state)
+{
+	mutex_lock(&dev_priv->csr_lock);
+	dev_priv->csr.state = state;
+	mutex_unlock(&dev_priv->csr_lock);
+}
+
 void intel_csr_load_program(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -204,6 +223,8 @@ void intel_csr_load_program(struct drm_device *dev)
 		I915_WRITE(dev_priv->csr.mmioaddr[i],
 			dev_priv->csr.mmiodata[i]);
 	}
+
+	dev_priv->csr.state = FW_LOADED;
 	mutex_unlock(&dev_priv->csr_lock);
 }
 
@@ -220,6 +241,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 	uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
 	uint32_t i;
 	__be32 *dmc_payload;
+	bool fw_loaded = false;
 
 	if (!fw) {
 		i915_firmware_load_error_print(csr->fw_path, 0);
@@ -326,7 +348,14 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 
 	/* load csr program during system boot, as needed for DC states */
 	intel_csr_load_program(dev);
+	fw_loaded = true;
+
 out:
+	if (fw_loaded)
+		intel_runtime_pm_put(dev_priv);
+	else
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
+
 	release_firmware(fw);
 }
 
@@ -343,17 +372,25 @@ void intel_csr_ucode_init(struct drm_device *dev)
 		csr->fw_path = I915_CSR_SKL;
 	else {
 		DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
 		return;
 	}
 
+	/*
+	 * Obtain a runtime pm reference, until CSR is loaded,
+	 * to avoid entering runtime-suspend.
+	 */
+	intel_runtime_pm_get(dev_priv);
+
 	/* CSR supported for platform, load firmware */
 	ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path,
 				&dev_priv->dev->pdev->dev,
 				GFP_KERNEL, dev_priv,
 				finish_csr_load);
-	if (ret)
+	if (ret) {
 		i915_firmware_load_error_print(csr->fw_path, ret);
-
+		intel_csr_load_status_set(dev_priv, FW_FAILED);
+	}
 }
 
 void intel_csr_ucode_fini(struct drm_device *dev)
@@ -363,5 +400,6 @@ void intel_csr_ucode_fini(struct drm_device *dev)
 	if (!HAS_CSR(dev))
 		return;
 
+	intel_csr_load_status_set(dev_priv, FW_FAILED);
 	kfree(dev_priv->csr.dmc_payload);
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f3a2d88..25d7956 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1064,6 +1064,9 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
 
 /* intel_csr.c */
 void intel_csr_ucode_init(struct drm_device *dev);
+enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv);
+void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
+					enum csr_state state);
 void intel_csr_load_program(struct drm_device *dev);
 void intel_csr_ucode_fini(struct drm_device *dev);
 
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index ce00e69..23f02a8 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -49,6 +49,8 @@
  * present for a given platform.
  */
 
+#define GEN9_ENABLE_DC5(dev) (IS_SKYLAKE(dev))
+
 #define for_each_power_well(i, power_well, domain_mask, power_domains)	\
 	for (i = 0;							\
 	     i < (power_domains)->power_well_count &&			\
@@ -319,9 +321,20 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
 	SKL_DISPLAY_MISC_IO_POWER_DOMAINS)) |		\
 	BIT(POWER_DOMAIN_INIT))
 
+static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
+{
+	/* TODO: Implementation to be done. */
+}
+
+static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
+{
+	/* TODO: Implementation to be done. */
+}
+
 static void skl_set_power_well(struct drm_i915_private *dev_priv,
 			struct i915_power_well *power_well, bool enable)
 {
+	struct drm_device *dev = dev_priv->dev;
 	uint32_t tmp, fuse_status;
 	uint32_t req_mask, state_mask;
 	bool is_enabled, enable_requested, check_fuse_status = false;
@@ -361,6 +374,13 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
 
 	if (enable) {
 		if (!enable_requested) {
+			WARN((tmp & state_mask) &&
+				!I915_READ(HSW_PWR_WELL_BIOS),
+				"Invalid for power well status to be enabled, unless done by the BIOS, \
+				when request is to disable!\n");
+			if (GEN9_ENABLE_DC5(dev) &&
+				power_well->data == SKL_DISP_PW_2)
+				gen9_disable_dc5(dev_priv);
 			I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask);
 		}
 
@@ -377,6 +397,19 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
 			I915_WRITE(HSW_PWR_WELL_DRIVER,	tmp & ~req_mask);
 			POSTING_READ(HSW_PWR_WELL_DRIVER);
 			DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
+
+			if (GEN9_ENABLE_DC5(dev) &&
+				power_well->data == SKL_DISP_PW_2) {
+				enum csr_state state;
+
+				wait_for((state = intel_csr_load_status_get(dev_priv)) !=
+						FW_UNINITIALIZED, 1000);
+				if (state != FW_LOADED)
+					DRM_ERROR("CSR firmware not ready (%d)\n",
+							state);
+				else
+					gen9_enable_dc5(dev_priv);
+			}
 		}
 	}
 
-- 
2.0.2

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

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

* Re: [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware.
  2015-04-16  8:52 ` [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
  2015-04-16  9:18   ` Damien Lespiau
  2015-04-16  9:21   ` Imre Deak
@ 2015-04-28 14:45   ` Imre Deak
  2015-04-29 17:29     ` [PATCH v5 " Animesh Manna
  2 siblings, 1 reply; 37+ messages in thread
From: Imre Deak @ 2015-04-28 14:45 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx

On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
> [...]
> +
> +#define I915_CSR_SKL "i915/skl_dmc_ver1.bin"

Animesh, does this firmware loading patchset work with skl_dmc_ver4.bin?
If so please re-send this patch with the above pointing to
i915/skl_dmc_ver4.bin (since that is the published firmware version).
Note that we can do this change now regardless of whether we decide
later to use a symlink or not.

--Imre


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

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

* [PATCH v5 1/8] drm/i915/skl: Add support to load SKL CSR firmware.
  2015-04-28 14:45   ` Imre Deak
@ 2015-04-29 17:29     ` Animesh Manna
  2015-04-30 13:02       ` Imre Deak
  2015-05-04 12:54       ` Daniel Vetter
  0 siblings, 2 replies; 37+ messages in thread
From: Animesh Manna @ 2015-04-29 17:29 UTC (permalink / raw)
  To: intel-gfx

From: "A.Sunil Kamath" <sunil.kamath@intel.com>

Display Context Save and Restore support is needed for
various SKL Display C states like DC5, DC6.

This implementation is added based on first version of DMC CSR program
that we received from h/w team.

Here we are using request_firmware based design.
Finally this firmware should end up in linux-firmware tree.

For SKL platform its mandatory to ensure that we load this
csr program before enabling DC states like DC5/DC6.

As CSR program gets reset on various conditions, we should ensure
to load it during boot and in future change to be added to load
this system resume sequence too.

v1: Initial relese as RFC patch

v2: Design change as per Daniel, Damien and Shobit's review comments
request firmware method followed.

v3: Some optimization and functional changes.
Pulled register defines into drivers/gpu/drm/i915/i915_reg.h
Used kmemdup to allocate and duplicate firmware content.
Ensured to free allocated buffer.

v4: Modified as per review comments from Satheesh and Daniel
Removed temporary buffer.
Optimized number of writes by replacing I915_WRITE with I915_WRITE64.

v5:
Modified as per review comemnts from Damien.
- Changed name for functions and firmware.
- Introduced HAS_CSR.
- Reverted back previous change and used csr_buf with u8 size.
- Using cpu_to_be64 for endianness change.

Modified as per review comments from Imre.
- Modified registers and macro names to be a bit closer to bspec terminology
and the existing register naming in the driver.
- Early return for non SKL platforms in intel_load_csr_program function.
- Added locking around CSR program load function as it may be called
concurrently during system/runtime resume.
- Releasing the fw before loading the program for consistency
- Handled error path during f/w load.

v6: Modified as per review comments from Imre.
- Corrected out_freecsr sequence.

v7: Modified as per review comments from Imre.
Fail loading fw if fw->size%8!=0.

v8: Rebase to latest.

v9: Rebase on top of -nightly (Damien)

v10: Enabled support for dmc firmware ver 1.0.
According to ver 1.0 in a single binary package all the firmware's that are
required for different stepping's of the product will be stored. The package
contains the css header, followed by the package header and the actual dmc
firmwares. Package header contains the firmware/stepping mapping table and
the corresponding firmware offsets to the individual binaries, within the
package. Each individual program binary contains the header and the payload
sections whose size is specified in the header section. This changes are done
to extract the specific firmaware from the package. (Animesh)

v11: Modified as per review comemnts from Imre.
- Added code comment from bpec for header structure elements.
- Added __packed to avoid structure padding.
- Added helper functions for stepping and substepping info.
- Added code comment for CSR_MAX_FW_SIZE.
- Disabled BXT firmware loading, will be enabled with dmc 1.0 support.
- Changed skl_stepping_info based on bspec, earlier used from config DB.
- Removed duplicate call of cpu_to_be* from intel_csr_load_program function.
- Used cpu_to_be32 instead of cpu_to_be64 as firmware binary in dword aligned.
- Added sanity check for header length.
- Added sanity check for mmio address got from firmware binary.
- kmalloc done separately for dmc header and dmc firmware. (Animesh)

v12: Modified as per review comemnts from Imre.
- Corrected the typo error in skl stepping info structure.
- Added out-of-bound access for skl_stepping_info.
- Sanity check for mmio address modified.
- Sanity check added for stepping and substeppig.
- Modified the intel_dmc_info structure, cache only the required header info. (Animesh)

v13: clarify firmware load error message.
The reason for a firmware loading failure can be obscure if the driver
is built-in. Provide an explanation to the user about the likely reason for
the failure and how to resolve it. (Imre)

v14: Suggested by Jani.
- fix s/I915/CONFIG_DRM_I915/ typo
- add fw_path to the firmware object instead of using a static ptr (Jani)

v15:
1) Changed the firmware name as dmc_gen9.bin, everytime for a new firmware version a symbolic link
with same name will help not to build kernel again.
2) Changes done as per review comments from Imre.
- Error check removed for intel_csr_ucode_init.
- Moved csr-specific data structure to intel_csr.h and optimization done on structure definition.
- fw->data used directly for parsing the header info & memory allocation
only done separately for payload. (Animesh)

v16:
- No need for out_regs label in i915_driver_load(), so removed it.
- Changed the firmware name as skl_dmc_ver1.bin, followed naming convention <platform>_dmc_<api-version>.bin (Animesh)

Issue: VIZ-2569
Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Animesh Manna <animesh.manna@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/Makefile    |   3 +-
 drivers/gpu/drm/i915/i915_dma.c  |  11 +-
 drivers/gpu/drm/i915/i915_drv.c  |  20 +++
 drivers/gpu/drm/i915/i915_drv.h  |  17 ++
 drivers/gpu/drm/i915/intel_csr.c | 367 +++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |   5 +
 6 files changed, 420 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_csr.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index a69002e..5238deb 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_csr.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 e44116f..a238889 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -816,6 +816,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	spin_lock_init(&dev_priv->mmio_flip_lock);
 	mutex_init(&dev_priv->dpio_lock);
 	mutex_init(&dev_priv->modeset_restore_lock);
+	mutex_init(&dev_priv->csr_lock);
 
 	intel_pm_setup(dev);
 
@@ -861,9 +862,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
 	intel_uncore_init(dev);
 
+	/* Load CSR Firmware for SKL */
+	intel_csr_ucode_init(dev);
+
 	ret = i915_gem_gtt_init(dev);
 	if (ret)
-		goto out_regs;
+		goto out_freecsr;
 
 	/* WARNING: Apparently we must kick fbdev drivers before vgacon,
 	 * otherwise the vga fbdev driver falls over. */
@@ -1033,7 +1037,8 @@ out_mtrrfree:
 	io_mapping_free(dev_priv->gtt.mappable);
 out_gtt:
 	i915_global_gtt_cleanup(dev);
-out_regs:
+out_freecsr:
+	intel_csr_ucode_fini(dev);
 	intel_uncore_fini(dev);
 	pci_iounmap(dev->pdev, dev_priv->regs);
 put_bridge:
@@ -1113,6 +1118,8 @@ int i915_driver_unload(struct drm_device *dev)
 	mutex_unlock(&dev->struct_mutex);
 	i915_gem_cleanup_stolen(dev);
 
+	intel_csr_ucode_fini(dev);
+
 	intel_teardown_gmbus(dev);
 	intel_teardown_mchbar(dev);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index c3fdbb0..acd0e2b 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -556,6 +556,26 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
 	cancel_delayed_work_sync(&dev_priv->hotplug_reenable_work);
 }
 
+void i915_firmware_load_error_print(const char *fw_path, int err)
+{
+	DRM_ERROR("failed to load firmware %s (%d)\n", fw_path, err);
+
+	/*
+	 * If the reason is not known assume -ENOENT since that's the most
+	 * usual failure mode.
+	 */
+	if (!err)
+		err = -ENOENT;
+
+	if (!(IS_BUILTIN(CONFIG_DRM_I915) && err == -ENOENT))
+		return;
+
+	DRM_ERROR(
+	  "The driver is built-in, so to load the firmware you need to\n"
+	  "include it either in the kernel (see CONFIG_EXTRA_FIRMWARE) or\n"
+	  "in your initrd/initramfs image.\n");
+}
+
 static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 47be4a5..90e47a9 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -667,6 +667,15 @@ struct intel_uncore {
 #define for_each_fw_domain(domain__, dev_priv__, i__) \
 	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
 
+struct intel_csr {
+	const char *fw_path;
+	__be32 *dmc_payload;
+	uint32_t dmc_fw_size;
+	uint32_t mmio_count;
+	uint32_t mmioaddr[8];
+	uint32_t mmiodata[8];
+};
+
 #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
 	func(is_mobile) sep \
 	func(is_i85x) sep \
@@ -1573,6 +1582,11 @@ struct drm_i915_private {
 
 	struct i915_virtual_gpu vgpu;
 
+	struct intel_csr csr;
+
+	/* Display CSR-related protection */
+	struct mutex csr_lock;
+
 	struct intel_gmbus gmbus[GMBUS_NUM_PINS];
 
 	/** gmbus_mutex protects against concurrent usage of the single hw gmbus
@@ -2425,6 +2439,8 @@ struct drm_i915_cmd_table {
 #define HAS_RC6(dev)		(INTEL_INFO(dev)->gen >= 6)
 #define HAS_RC6p(dev)		(INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
 
+#define HAS_CSR(dev)	(IS_SKYLAKE(dev))
+
 #define INTEL_PCH_DEVICE_ID_MASK		0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
 #define INTEL_PCH_CPT_DEVICE_ID_TYPE		0x1c00
@@ -2515,6 +2531,7 @@ extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
 extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
 int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
 void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
+void i915_firmware_load_error_print(const char *fw_path, int err);
 
 /* i915_irq.c */
 void i915_queue_hangcheck(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
new file mode 100644
index 0000000..f5fa574
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+#include <linux/firmware.h>
+#include "i915_drv.h"
+#include "i915_reg.h"
+
+#define I915_CSR_SKL "i915/skl_dmc_ver4.bin"
+
+MODULE_FIRMWARE(I915_CSR_SKL);
+
+/*
+* SKL CSR registers for DC5 and DC6
+*/
+#define CSR_PROGRAM_BASE		0x80000
+#define CSR_SSP_BASE_ADDR_GEN9		0x00002FC0
+#define CSR_HTP_ADDR_SKL		0x00500034
+#define CSR_SSP_BASE			0x8F074
+#define CSR_HTP_SKL			0x8F004
+#define CSR_LAST_WRITE			0x8F034
+#define CSR_LAST_WRITE_VALUE		0xc003b400
+/* MMIO address range for CSR program (0x80000 - 0x82FFF) */
+#define CSR_MAX_FW_SIZE			0x2FFF
+#define CSR_DEFAULT_FW_OFFSET		0xFFFFFFFF
+#define CSR_MMIO_START_RANGE	0x80000
+#define CSR_MMIO_END_RANGE		0x8FFFF
+
+struct intel_css_header {
+	/* 0x09 for DMC */
+	uint32_t module_type;
+
+	/* Includes the DMC specific header in dwords */
+	uint32_t header_len;
+
+	/* always value would be 0x10000 */
+	uint32_t header_ver;
+
+	/* Not used */
+	uint32_t module_id;
+
+	/* Not used */
+	uint32_t module_vendor;
+
+	/* in YYYYMMDD format */
+	uint32_t date;
+
+	/* Size in dwords (CSS_Headerlen + PackageHeaderLen + dmc FWsLen)/4 */
+	uint32_t size;
+
+	/* Not used */
+	uint32_t key_size;
+
+	/* Not used */
+	uint32_t modulus_size;
+
+	/* Not used */
+	uint32_t exponent_size;
+
+	/* Not used */
+	uint32_t reserved1[12];
+
+	/* Major Minor */
+	uint32_t version;
+
+	/* Not used */
+	uint32_t reserved2[8];
+
+	/* Not used */
+	uint32_t kernel_header_info;
+} __packed;
+
+struct intel_fw_info {
+	uint16_t reserved1;
+
+	/* Stepping (A, B, C, ..., *). * is a wildcard */
+	char stepping;
+
+	/* Sub-stepping (0, 1, ..., *). * is a wildcard */
+	char substepping;
+
+	uint32_t offset;
+	uint32_t reserved2;
+} __packed;
+
+struct intel_package_header {
+	/* DMC container header length in dwords */
+	unsigned char header_len;
+
+	/* always value would be 0x01 */
+	unsigned char header_ver;
+
+	unsigned char reserved[10];
+
+	/* Number of valid entries in the FWInfo array below */
+	uint32_t num_entries;
+
+	struct intel_fw_info fw_info[20];
+} __packed;
+
+struct intel_dmc_header {
+	/* always value would be 0x40403E3E */
+	uint32_t signature;
+
+	/* DMC binary header length */
+	unsigned char header_len;
+
+	/* 0x01 */
+	unsigned char header_ver;
+
+	/* Reserved */
+	uint16_t dmcc_ver;
+
+	/* Major, Minor */
+	uint32_t	project;
+
+	/* Firmware program size (excluding header) in dwords */
+	uint32_t	fw_size;
+
+	/* Major Minor version */
+	uint32_t fw_version;
+
+	/* Number of valid MMIO cycles present. */
+	uint32_t mmio_count;
+
+	/* MMIO address */
+	uint32_t mmioaddr[8];
+
+	/* MMIO data */
+	uint32_t mmiodata[8];
+
+	/* FW filename  */
+	unsigned char dfile[32];
+
+	uint32_t reserved1[2];
+} __packed;
+
+struct stepping_info {
+	char stepping;
+	char substepping;
+};
+
+static const struct stepping_info skl_stepping_info[] = {
+		{'A', '0'}, {'B', '0'}, {'C', '0'},
+		{'D', '0'}, {'E', '0'}, {'F', '0'},
+		{'G', '0'}, {'H', '0'}, {'I', '0'}
+};
+
+static char intel_get_stepping(struct drm_device *dev)
+{
+	if (IS_SKYLAKE(dev) && (dev->pdev->revision <
+			ARRAY_SIZE(skl_stepping_info)))
+		return skl_stepping_info[dev->pdev->revision].stepping;
+	else
+		return -ENODATA;
+}
+
+static char intel_get_substepping(struct drm_device *dev)
+{
+	if (IS_SKYLAKE(dev) && (dev->pdev->revision <
+			ARRAY_SIZE(skl_stepping_info)))
+		return skl_stepping_info[dev->pdev->revision].substepping;
+	else
+		return -ENODATA;
+}
+
+void intel_csr_load_program(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	__be32 *payload = dev_priv->csr.dmc_payload;
+	uint32_t i, fw_size;
+
+	if (!IS_GEN9(dev)) {
+		DRM_ERROR("No CSR support available for this platform\n");
+		return;
+	}
+
+	mutex_lock(&dev_priv->csr_lock);
+	fw_size = dev_priv->csr.dmc_fw_size;
+	for (i = 0; i < fw_size; i++)
+		I915_WRITE(CSR_PROGRAM_BASE + i * 4,
+			(u32 __force)payload[i]);
+
+	for (i = 0; i < dev_priv->csr.mmio_count; i++) {
+		I915_WRITE(dev_priv->csr.mmioaddr[i],
+			dev_priv->csr.mmiodata[i]);
+	}
+	mutex_unlock(&dev_priv->csr_lock);
+}
+
+static void finish_csr_load(const struct firmware *fw, void *context)
+{
+	struct drm_i915_private *dev_priv = context;
+	struct drm_device *dev = dev_priv->dev;
+	struct intel_css_header *css_header;
+	struct intel_package_header *package_header;
+	struct intel_dmc_header *dmc_header;
+	struct intel_csr *csr = &dev_priv->csr;
+	char stepping = intel_get_stepping(dev);
+	char substepping = intel_get_substepping(dev);
+	uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
+	uint32_t i;
+	__be32 *dmc_payload;
+
+	if (!fw) {
+		i915_firmware_load_error_print(csr->fw_path, 0);
+		goto out;
+	}
+
+	if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
+		DRM_ERROR("Unknown stepping info, firmware loading failed\n");
+		goto out;
+	}
+
+	/* Extract CSS Header information*/
+	css_header = (struct intel_css_header *)fw->data;
+	if (sizeof(struct intel_css_header) !=
+		(css_header->header_len * 4)) {
+		DRM_ERROR("Firmware has wrong CSS header length %u bytes\n",
+			(css_header->header_len * 4));
+		goto out;
+	}
+	readcount += sizeof(struct intel_css_header);
+
+	/* Extract Package Header information*/
+	package_header = (struct intel_package_header *)
+					&fw->data[readcount];
+	if (sizeof(struct intel_package_header) !=
+		(package_header->header_len * 4)) {
+		DRM_ERROR("Firmware has wrong package header length %u bytes\n",
+			(package_header->header_len * 4));
+		goto out;
+	}
+	readcount += sizeof(struct intel_package_header);
+
+	/* Search for dmc_offset to find firware binary. */
+	for (i = 0; i < package_header->num_entries; i++) {
+		if (package_header->fw_info[i].substepping == '*' &&
+			stepping == package_header->fw_info[i].stepping) {
+			dmc_offset = package_header->fw_info[i].offset;
+			break;
+		} else if (stepping == package_header->fw_info[i].stepping &&
+			substepping == package_header->fw_info[i].substepping) {
+			dmc_offset = package_header->fw_info[i].offset;
+			break;
+		} else if (package_header->fw_info[i].stepping == '*' &&
+			package_header->fw_info[i].substepping == '*')
+			dmc_offset = package_header->fw_info[i].offset;
+	}
+	if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
+		DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
+		goto out;
+	}
+	readcount += dmc_offset;
+
+	/* Extract dmc_header information. */
+	dmc_header = (struct intel_dmc_header *)&fw->data[readcount];
+	if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) {
+		DRM_ERROR("Firmware has wrong dmc header length %u bytes\n",
+				(dmc_header->header_len));
+		goto out;
+	}
+	readcount += sizeof(struct intel_dmc_header);
+
+	/* Cache the dmc header info. */
+	if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) {
+		DRM_ERROR("Firmware has wrong mmio count %u\n",
+						dmc_header->mmio_count);
+		goto out;
+	}
+	csr->mmio_count = dmc_header->mmio_count;
+	for (i = 0; i < dmc_header->mmio_count; i++) {
+		if (dmc_header->mmioaddr[i] < CSR_MMIO_START_RANGE &&
+			dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
+			DRM_ERROR(" Firmware has wrong mmio address 0x%x\n",
+						dmc_header->mmioaddr[i]);
+			goto out;
+		}
+		csr->mmioaddr[i] = dmc_header->mmioaddr[i];
+		csr->mmiodata[i] = dmc_header->mmiodata[i];
+	}
+
+	/* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
+	nbytes = dmc_header->fw_size * 4;
+	if (nbytes > CSR_MAX_FW_SIZE) {
+		DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes);
+		goto out;
+	}
+	csr->dmc_fw_size = dmc_header->fw_size;
+
+	csr->dmc_payload = kmalloc(nbytes, GFP_KERNEL);
+	if (!csr->dmc_payload) {
+		DRM_ERROR("Memory allocation failed for dmc payload\n");
+		goto out;
+	}
+
+	dmc_payload = csr->dmc_payload;
+	for (i = 0; i < dmc_header->fw_size; i++) {
+		uint32_t *tmp = (u32 *)&fw->data[readcount + i * 4];
+		/*
+		 * The firmware payload is an array of 32 bit words stored in
+		 * little-endian format in the firmware image and programmed
+		 * as 32 bit big-endian format to memory.
+		 */
+		dmc_payload[i] = cpu_to_be32(*tmp);
+	}
+
+	/* load csr program during system boot, as needed for DC states */
+	intel_csr_load_program(dev);
+out:
+	release_firmware(fw);
+}
+
+void intel_csr_ucode_init(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_csr *csr = &dev_priv->csr;
+	int ret;
+
+	if (!HAS_CSR(dev))
+		return;
+
+	if (IS_SKYLAKE(dev))
+		csr->fw_path = I915_CSR_SKL;
+	else {
+		DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
+		return;
+	}
+
+	/* CSR supported for platform, load firmware */
+	ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path,
+				&dev_priv->dev->pdev->dev,
+				GFP_KERNEL, dev_priv,
+				finish_csr_load);
+	if (ret)
+		i915_firmware_load_error_print(csr->fw_path, ret);
+
+}
+
+void intel_csr_ucode_fini(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (!HAS_CSR(dev))
+		return;
+
+	kfree(dev_priv->csr.dmc_payload);
+}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 7a0aa24..f3a2d88 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1062,6 +1062,11 @@ void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
 unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
 				     struct drm_i915_gem_object *obj);
 
+/* intel_csr.c */
+void intel_csr_ucode_init(struct drm_device *dev);
+void intel_csr_load_program(struct drm_device *dev);
+void intel_csr_ucode_fini(struct drm_device *dev);
+
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
 bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
-- 
2.0.2

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

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

* Re: [PATCH v5 1/8] drm/i915/skl: Add support to load SKL CSR firmware.
  2015-04-29 17:29     ` [PATCH v5 " Animesh Manna
@ 2015-04-30 13:02       ` Imre Deak
  2015-05-04  9:30         ` Daniel Vetter
  2015-05-04 12:54       ` Daniel Vetter
  1 sibling, 1 reply; 37+ messages in thread
From: Imre Deak @ 2015-04-30 13:02 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx

On ke, 2015-04-29 at 22:59 +0530, Animesh Manna wrote:
> From: "A.Sunil Kamath" <sunil.kamath@intel.com>
> 
> Display Context Save and Restore support is needed for
> various SKL Display C states like DC5, DC6.
> 
> This implementation is added based on first version of DMC CSR program
> that we received from h/w team.
> 
> Here we are using request_firmware based design.
> Finally this firmware should end up in linux-firmware tree.
> 
> For SKL platform its mandatory to ensure that we load this
> csr program before enabling DC states like DC5/DC6.
> 
> As CSR program gets reset on various conditions, we should ensure
> to load it during boot and in future change to be added to load
> this system resume sequence too.
> 
> v1: Initial relese as RFC patch
> 
> v2: Design change as per Daniel, Damien and Shobit's review comments
> request firmware method followed.
> 
> v3: Some optimization and functional changes.
> Pulled register defines into drivers/gpu/drm/i915/i915_reg.h
> Used kmemdup to allocate and duplicate firmware content.
> Ensured to free allocated buffer.
> 
> v4: Modified as per review comments from Satheesh and Daniel
> Removed temporary buffer.
> Optimized number of writes by replacing I915_WRITE with I915_WRITE64.
> 
> v5:
> Modified as per review comemnts from Damien.
> - Changed name for functions and firmware.
> - Introduced HAS_CSR.
> - Reverted back previous change and used csr_buf with u8 size.
> - Using cpu_to_be64 for endianness change.
> 
> Modified as per review comments from Imre.
> - Modified registers and macro names to be a bit closer to bspec terminology
> and the existing register naming in the driver.
> - Early return for non SKL platforms in intel_load_csr_program function.
> - Added locking around CSR program load function as it may be called
> concurrently during system/runtime resume.
> - Releasing the fw before loading the program for consistency
> - Handled error path during f/w load.
> 
> v6: Modified as per review comments from Imre.
> - Corrected out_freecsr sequence.
> 
> v7: Modified as per review comments from Imre.
> Fail loading fw if fw->size%8!=0.
> 
> v8: Rebase to latest.
> 
> v9: Rebase on top of -nightly (Damien)
> 
> v10: Enabled support for dmc firmware ver 1.0.
> According to ver 1.0 in a single binary package all the firmware's that are
> required for different stepping's of the product will be stored. The package
> contains the css header, followed by the package header and the actual dmc
> firmwares. Package header contains the firmware/stepping mapping table and
> the corresponding firmware offsets to the individual binaries, within the
> package. Each individual program binary contains the header and the payload
> sections whose size is specified in the header section. This changes are done
> to extract the specific firmaware from the package. (Animesh)
> 
> v11: Modified as per review comemnts from Imre.
> - Added code comment from bpec for header structure elements.
> - Added __packed to avoid structure padding.
> - Added helper functions for stepping and substepping info.
> - Added code comment for CSR_MAX_FW_SIZE.
> - Disabled BXT firmware loading, will be enabled with dmc 1.0 support.
> - Changed skl_stepping_info based on bspec, earlier used from config DB.
> - Removed duplicate call of cpu_to_be* from intel_csr_load_program function.
> - Used cpu_to_be32 instead of cpu_to_be64 as firmware binary in dword aligned.
> - Added sanity check for header length.
> - Added sanity check for mmio address got from firmware binary.
> - kmalloc done separately for dmc header and dmc firmware. (Animesh)
> 
> v12: Modified as per review comemnts from Imre.
> - Corrected the typo error in skl stepping info structure.
> - Added out-of-bound access for skl_stepping_info.
> - Sanity check for mmio address modified.
> - Sanity check added for stepping and substeppig.
> - Modified the intel_dmc_info structure, cache only the required header info. (Animesh)
> 
> v13: clarify firmware load error message.
> The reason for a firmware loading failure can be obscure if the driver
> is built-in. Provide an explanation to the user about the likely reason for
> the failure and how to resolve it. (Imre)
> 
> v14: Suggested by Jani.
> - fix s/I915/CONFIG_DRM_I915/ typo
> - add fw_path to the firmware object instead of using a static ptr (Jani)
> 
> v15:
> 1) Changed the firmware name as dmc_gen9.bin, everytime for a new firmware version a symbolic link
> with same name will help not to build kernel again.
> 2) Changes done as per review comments from Imre.
> - Error check removed for intel_csr_ucode_init.
> - Moved csr-specific data structure to intel_csr.h and optimization done on structure definition.
> - fw->data used directly for parsing the header info & memory allocation
> only done separately for payload. (Animesh)
> 
> v16:
> - No need for out_regs label in i915_driver_load(), so removed it.
> - Changed the firmware name as skl_dmc_ver1.bin, followed naming convention <platform>_dmc_<api-version>.bin (Animesh)
> 
> Issue: VIZ-2569
> Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>

For the future: scripts/checkpatch.pl has a valid warning about the
commit message, please fix the issues reported by this tool next time.

Reviewed-by: Imre Deak <imre.deak@intel.com>

> ---
>  drivers/gpu/drm/i915/Makefile    |   3 +-
>  drivers/gpu/drm/i915/i915_dma.c  |  11 +-
>  drivers/gpu/drm/i915/i915_drv.c  |  20 +++
>  drivers/gpu/drm/i915/i915_drv.h  |  17 ++
>  drivers/gpu/drm/i915/intel_csr.c | 367 +++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h |   5 +
>  6 files changed, 420 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/intel_csr.c
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index a69002e..5238deb 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_csr.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 e44116f..a238889 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -816,6 +816,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  	spin_lock_init(&dev_priv->mmio_flip_lock);
>  	mutex_init(&dev_priv->dpio_lock);
>  	mutex_init(&dev_priv->modeset_restore_lock);
> +	mutex_init(&dev_priv->csr_lock);
>  
>  	intel_pm_setup(dev);
>  
> @@ -861,9 +862,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  
>  	intel_uncore_init(dev);
>  
> +	/* Load CSR Firmware for SKL */
> +	intel_csr_ucode_init(dev);
> +
>  	ret = i915_gem_gtt_init(dev);
>  	if (ret)
> -		goto out_regs;
> +		goto out_freecsr;
>  
>  	/* WARNING: Apparently we must kick fbdev drivers before vgacon,
>  	 * otherwise the vga fbdev driver falls over. */
> @@ -1033,7 +1037,8 @@ out_mtrrfree:
>  	io_mapping_free(dev_priv->gtt.mappable);
>  out_gtt:
>  	i915_global_gtt_cleanup(dev);
> -out_regs:
> +out_freecsr:
> +	intel_csr_ucode_fini(dev);
>  	intel_uncore_fini(dev);
>  	pci_iounmap(dev->pdev, dev_priv->regs);
>  put_bridge:
> @@ -1113,6 +1118,8 @@ int i915_driver_unload(struct drm_device *dev)
>  	mutex_unlock(&dev->struct_mutex);
>  	i915_gem_cleanup_stolen(dev);
>  
> +	intel_csr_ucode_fini(dev);
> +
>  	intel_teardown_gmbus(dev);
>  	intel_teardown_mchbar(dev);
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index c3fdbb0..acd0e2b 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -556,6 +556,26 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
>  	cancel_delayed_work_sync(&dev_priv->hotplug_reenable_work);
>  }
>  
> +void i915_firmware_load_error_print(const char *fw_path, int err)
> +{
> +	DRM_ERROR("failed to load firmware %s (%d)\n", fw_path, err);
> +
> +	/*
> +	 * If the reason is not known assume -ENOENT since that's the most
> +	 * usual failure mode.
> +	 */
> +	if (!err)
> +		err = -ENOENT;
> +
> +	if (!(IS_BUILTIN(CONFIG_DRM_I915) && err == -ENOENT))
> +		return;
> +
> +	DRM_ERROR(
> +	  "The driver is built-in, so to load the firmware you need to\n"
> +	  "include it either in the kernel (see CONFIG_EXTRA_FIRMWARE) or\n"
> +	  "in your initrd/initramfs image.\n");
> +}
> +
>  static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
>  {
>  	struct drm_device *dev = dev_priv->dev;
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 47be4a5..90e47a9 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -667,6 +667,15 @@ struct intel_uncore {
>  #define for_each_fw_domain(domain__, dev_priv__, i__) \
>  	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
>  
> +struct intel_csr {
> +	const char *fw_path;
> +	__be32 *dmc_payload;
> +	uint32_t dmc_fw_size;
> +	uint32_t mmio_count;
> +	uint32_t mmioaddr[8];
> +	uint32_t mmiodata[8];
> +};
> +
>  #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
>  	func(is_mobile) sep \
>  	func(is_i85x) sep \
> @@ -1573,6 +1582,11 @@ struct drm_i915_private {
>  
>  	struct i915_virtual_gpu vgpu;
>  
> +	struct intel_csr csr;
> +
> +	/* Display CSR-related protection */
> +	struct mutex csr_lock;
> +
>  	struct intel_gmbus gmbus[GMBUS_NUM_PINS];
>  
>  	/** gmbus_mutex protects against concurrent usage of the single hw gmbus
> @@ -2425,6 +2439,8 @@ struct drm_i915_cmd_table {
>  #define HAS_RC6(dev)		(INTEL_INFO(dev)->gen >= 6)
>  #define HAS_RC6p(dev)		(INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
>  
> +#define HAS_CSR(dev)	(IS_SKYLAKE(dev))
> +
>  #define INTEL_PCH_DEVICE_ID_MASK		0xff00
>  #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
>  #define INTEL_PCH_CPT_DEVICE_ID_TYPE		0x1c00
> @@ -2515,6 +2531,7 @@ extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
>  extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
>  int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
>  void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
> +void i915_firmware_load_error_print(const char *fw_path, int err);
>  
>  /* i915_irq.c */
>  void i915_queue_hangcheck(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
> new file mode 100644
> index 0000000..f5fa574
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_csr.c
> @@ -0,0 +1,367 @@
> +/*
> + * Copyright © 2014 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +#include <linux/firmware.h>
> +#include "i915_drv.h"
> +#include "i915_reg.h"
> +
> +#define I915_CSR_SKL "i915/skl_dmc_ver4.bin"
> +
> +MODULE_FIRMWARE(I915_CSR_SKL);
> +
> +/*
> +* SKL CSR registers for DC5 and DC6
> +*/
> +#define CSR_PROGRAM_BASE		0x80000
> +#define CSR_SSP_BASE_ADDR_GEN9		0x00002FC0
> +#define CSR_HTP_ADDR_SKL		0x00500034
> +#define CSR_SSP_BASE			0x8F074
> +#define CSR_HTP_SKL			0x8F004
> +#define CSR_LAST_WRITE			0x8F034
> +#define CSR_LAST_WRITE_VALUE		0xc003b400
> +/* MMIO address range for CSR program (0x80000 - 0x82FFF) */
> +#define CSR_MAX_FW_SIZE			0x2FFF
> +#define CSR_DEFAULT_FW_OFFSET		0xFFFFFFFF
> +#define CSR_MMIO_START_RANGE	0x80000
> +#define CSR_MMIO_END_RANGE		0x8FFFF
> +
> +struct intel_css_header {
> +	/* 0x09 for DMC */
> +	uint32_t module_type;
> +
> +	/* Includes the DMC specific header in dwords */
> +	uint32_t header_len;
> +
> +	/* always value would be 0x10000 */
> +	uint32_t header_ver;
> +
> +	/* Not used */
> +	uint32_t module_id;
> +
> +	/* Not used */
> +	uint32_t module_vendor;
> +
> +	/* in YYYYMMDD format */
> +	uint32_t date;
> +
> +	/* Size in dwords (CSS_Headerlen + PackageHeaderLen + dmc FWsLen)/4 */
> +	uint32_t size;
> +
> +	/* Not used */
> +	uint32_t key_size;
> +
> +	/* Not used */
> +	uint32_t modulus_size;
> +
> +	/* Not used */
> +	uint32_t exponent_size;
> +
> +	/* Not used */
> +	uint32_t reserved1[12];
> +
> +	/* Major Minor */
> +	uint32_t version;
> +
> +	/* Not used */
> +	uint32_t reserved2[8];
> +
> +	/* Not used */
> +	uint32_t kernel_header_info;
> +} __packed;
> +
> +struct intel_fw_info {
> +	uint16_t reserved1;
> +
> +	/* Stepping (A, B, C, ..., *). * is a wildcard */
> +	char stepping;
> +
> +	/* Sub-stepping (0, 1, ..., *). * is a wildcard */
> +	char substepping;
> +
> +	uint32_t offset;
> +	uint32_t reserved2;
> +} __packed;
> +
> +struct intel_package_header {
> +	/* DMC container header length in dwords */
> +	unsigned char header_len;
> +
> +	/* always value would be 0x01 */
> +	unsigned char header_ver;
> +
> +	unsigned char reserved[10];
> +
> +	/* Number of valid entries in the FWInfo array below */
> +	uint32_t num_entries;
> +
> +	struct intel_fw_info fw_info[20];
> +} __packed;
> +
> +struct intel_dmc_header {
> +	/* always value would be 0x40403E3E */
> +	uint32_t signature;
> +
> +	/* DMC binary header length */
> +	unsigned char header_len;
> +
> +	/* 0x01 */
> +	unsigned char header_ver;
> +
> +	/* Reserved */
> +	uint16_t dmcc_ver;
> +
> +	/* Major, Minor */
> +	uint32_t	project;
> +
> +	/* Firmware program size (excluding header) in dwords */
> +	uint32_t	fw_size;
> +
> +	/* Major Minor version */
> +	uint32_t fw_version;
> +
> +	/* Number of valid MMIO cycles present. */
> +	uint32_t mmio_count;
> +
> +	/* MMIO address */
> +	uint32_t mmioaddr[8];
> +
> +	/* MMIO data */
> +	uint32_t mmiodata[8];
> +
> +	/* FW filename  */
> +	unsigned char dfile[32];
> +
> +	uint32_t reserved1[2];
> +} __packed;
> +
> +struct stepping_info {
> +	char stepping;
> +	char substepping;
> +};
> +
> +static const struct stepping_info skl_stepping_info[] = {
> +		{'A', '0'}, {'B', '0'}, {'C', '0'},
> +		{'D', '0'}, {'E', '0'}, {'F', '0'},
> +		{'G', '0'}, {'H', '0'}, {'I', '0'}
> +};
> +
> +static char intel_get_stepping(struct drm_device *dev)
> +{
> +	if (IS_SKYLAKE(dev) && (dev->pdev->revision <
> +			ARRAY_SIZE(skl_stepping_info)))
> +		return skl_stepping_info[dev->pdev->revision].stepping;
> +	else
> +		return -ENODATA;
> +}
> +
> +static char intel_get_substepping(struct drm_device *dev)
> +{
> +	if (IS_SKYLAKE(dev) && (dev->pdev->revision <
> +			ARRAY_SIZE(skl_stepping_info)))
> +		return skl_stepping_info[dev->pdev->revision].substepping;
> +	else
> +		return -ENODATA;
> +}
> +
> +void intel_csr_load_program(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	__be32 *payload = dev_priv->csr.dmc_payload;
> +	uint32_t i, fw_size;
> +
> +	if (!IS_GEN9(dev)) {
> +		DRM_ERROR("No CSR support available for this platform\n");
> +		return;
> +	}
> +
> +	mutex_lock(&dev_priv->csr_lock);
> +	fw_size = dev_priv->csr.dmc_fw_size;
> +	for (i = 0; i < fw_size; i++)
> +		I915_WRITE(CSR_PROGRAM_BASE + i * 4,
> +			(u32 __force)payload[i]);
> +
> +	for (i = 0; i < dev_priv->csr.mmio_count; i++) {
> +		I915_WRITE(dev_priv->csr.mmioaddr[i],
> +			dev_priv->csr.mmiodata[i]);
> +	}
> +	mutex_unlock(&dev_priv->csr_lock);
> +}
> +
> +static void finish_csr_load(const struct firmware *fw, void *context)
> +{
> +	struct drm_i915_private *dev_priv = context;
> +	struct drm_device *dev = dev_priv->dev;
> +	struct intel_css_header *css_header;
> +	struct intel_package_header *package_header;
> +	struct intel_dmc_header *dmc_header;
> +	struct intel_csr *csr = &dev_priv->csr;
> +	char stepping = intel_get_stepping(dev);
> +	char substepping = intel_get_substepping(dev);
> +	uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
> +	uint32_t i;
> +	__be32 *dmc_payload;
> +
> +	if (!fw) {
> +		i915_firmware_load_error_print(csr->fw_path, 0);
> +		goto out;
> +	}
> +
> +	if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
> +		DRM_ERROR("Unknown stepping info, firmware loading failed\n");
> +		goto out;
> +	}
> +
> +	/* Extract CSS Header information*/
> +	css_header = (struct intel_css_header *)fw->data;
> +	if (sizeof(struct intel_css_header) !=
> +		(css_header->header_len * 4)) {
> +		DRM_ERROR("Firmware has wrong CSS header length %u bytes\n",
> +			(css_header->header_len * 4));
> +		goto out;
> +	}
> +	readcount += sizeof(struct intel_css_header);
> +
> +	/* Extract Package Header information*/
> +	package_header = (struct intel_package_header *)
> +					&fw->data[readcount];
> +	if (sizeof(struct intel_package_header) !=
> +		(package_header->header_len * 4)) {
> +		DRM_ERROR("Firmware has wrong package header length %u bytes\n",
> +			(package_header->header_len * 4));
> +		goto out;
> +	}
> +	readcount += sizeof(struct intel_package_header);
> +
> +	/* Search for dmc_offset to find firware binary. */
> +	for (i = 0; i < package_header->num_entries; i++) {
> +		if (package_header->fw_info[i].substepping == '*' &&
> +			stepping == package_header->fw_info[i].stepping) {
> +			dmc_offset = package_header->fw_info[i].offset;
> +			break;
> +		} else if (stepping == package_header->fw_info[i].stepping &&
> +			substepping == package_header->fw_info[i].substepping) {
> +			dmc_offset = package_header->fw_info[i].offset;
> +			break;
> +		} else if (package_header->fw_info[i].stepping == '*' &&
> +			package_header->fw_info[i].substepping == '*')
> +			dmc_offset = package_header->fw_info[i].offset;
> +	}
> +	if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
> +		DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
> +		goto out;
> +	}
> +	readcount += dmc_offset;
> +
> +	/* Extract dmc_header information. */
> +	dmc_header = (struct intel_dmc_header *)&fw->data[readcount];
> +	if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) {
> +		DRM_ERROR("Firmware has wrong dmc header length %u bytes\n",
> +				(dmc_header->header_len));
> +		goto out;
> +	}
> +	readcount += sizeof(struct intel_dmc_header);
> +
> +	/* Cache the dmc header info. */
> +	if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) {
> +		DRM_ERROR("Firmware has wrong mmio count %u\n",
> +						dmc_header->mmio_count);
> +		goto out;
> +	}
> +	csr->mmio_count = dmc_header->mmio_count;
> +	for (i = 0; i < dmc_header->mmio_count; i++) {
> +		if (dmc_header->mmioaddr[i] < CSR_MMIO_START_RANGE &&
> +			dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
> +			DRM_ERROR(" Firmware has wrong mmio address 0x%x\n",
> +						dmc_header->mmioaddr[i]);
> +			goto out;
> +		}
> +		csr->mmioaddr[i] = dmc_header->mmioaddr[i];
> +		csr->mmiodata[i] = dmc_header->mmiodata[i];
> +	}
> +
> +	/* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
> +	nbytes = dmc_header->fw_size * 4;
> +	if (nbytes > CSR_MAX_FW_SIZE) {
> +		DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes);
> +		goto out;
> +	}
> +	csr->dmc_fw_size = dmc_header->fw_size;
> +
> +	csr->dmc_payload = kmalloc(nbytes, GFP_KERNEL);
> +	if (!csr->dmc_payload) {
> +		DRM_ERROR("Memory allocation failed for dmc payload\n");
> +		goto out;
> +	}
> +
> +	dmc_payload = csr->dmc_payload;
> +	for (i = 0; i < dmc_header->fw_size; i++) {
> +		uint32_t *tmp = (u32 *)&fw->data[readcount + i * 4];
> +		/*
> +		 * The firmware payload is an array of 32 bit words stored in
> +		 * little-endian format in the firmware image and programmed
> +		 * as 32 bit big-endian format to memory.
> +		 */
> +		dmc_payload[i] = cpu_to_be32(*tmp);
> +	}
> +
> +	/* load csr program during system boot, as needed for DC states */
> +	intel_csr_load_program(dev);
> +out:
> +	release_firmware(fw);
> +}
> +
> +void intel_csr_ucode_init(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_csr *csr = &dev_priv->csr;
> +	int ret;
> +
> +	if (!HAS_CSR(dev))
> +		return;
> +
> +	if (IS_SKYLAKE(dev))
> +		csr->fw_path = I915_CSR_SKL;
> +	else {
> +		DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
> +		return;
> +	}
> +
> +	/* CSR supported for platform, load firmware */
> +	ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path,
> +				&dev_priv->dev->pdev->dev,
> +				GFP_KERNEL, dev_priv,
> +				finish_csr_load);
> +	if (ret)
> +		i915_firmware_load_error_print(csr->fw_path, ret);
> +
> +}
> +
> +void intel_csr_ucode_fini(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	if (!HAS_CSR(dev))
> +		return;
> +
> +	kfree(dev_priv->csr.dmc_payload);
> +}
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 7a0aa24..f3a2d88 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1062,6 +1062,11 @@ void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
>  unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
>  				     struct drm_i915_gem_object *obj);
>  
> +/* intel_csr.c */
> +void intel_csr_ucode_init(struct drm_device *dev);
> +void intel_csr_load_program(struct drm_device *dev);
> +void intel_csr_ucode_fini(struct drm_device *dev);
> +
>  /* intel_dp.c */
>  void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
>  bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,


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

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

* Re: [PATCH v5 2/2] drm/i915/skl: Add DC5 Trigger Sequence
  2015-04-17 14:16           ` [PATCH v5 2/2] " Animesh Manna
@ 2015-04-30 13:18             ` Imre Deak
  2015-05-04  9:39             ` Daniel Vetter
  1 sibling, 0 replies; 37+ messages in thread
From: Imre Deak @ 2015-04-30 13:18 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On pe, 2015-04-17 at 19:46 +0530, Animesh Manna wrote:
> From: Suketu Shah <suketu.j.shah@intel.com>
> 
> Add triggers as per expectations mentioned in gen9_enable_dc5
> and gen9_disable_dc5 patch.
> 
> Also call POSTING_READ for every write to a register to ensure that
> its written immediately.
> 
> v1: Remove POSTING_READ calls as they've already been added in previous patches.
> 
> v2: Rebase to move all runtime pm specific changes to intel_runtime_pm.c file.
> 
> Modified as per review comments from Imre:
> 1] Change variable name 'dc5_allowed' to 'dc5_enabled' to correspond to relevant
>    functions.
> 2] Move the check dc5_enabled in skl_set_power_well() to disable DC5 into
>    gen9_disable_DC5 which is a more appropriate place.
> 3] Convert checks for 'pm.dc5_enabled' and 'pm.suspended' in skl_set_power_well()
>    to warnings. However, removing them for now as they'll be included in a future patch
>    asserting DC-state entry/exit criteria.
> 4] Enable DC5, only when CSR firmware is verified to be loaded. Create new structure
>    to track 'enabled' and 'deferred' status of DC5.
> 5] Ensure runtime PM reference is obtained, if CSR is not loaded, to avoid entering
>    runtime-suspend and release it when it's loaded.
> 6] Protect necessary CSR-related code with locks.
> 7] Move CSR-loading call to runtime PM initialization, as power domains needed to be
>    accessed during deferred DC5-enabling, are not initialized earlier.
> 
> v3: Rebase to latest.
> 
> Modified as per review comments from Imre:
> 1] Use blocking wait for CSR-loading to finish to enable DC5  for simplicity, instead of
>    deferring enabling DC5 until CSR is loaded.
> 2] Obtain runtime PM reference during CSR-loading initialization itself as deferred DC5-
>    enabling is removed and release it at the end of CSR-loading functionality.
> 3] Revert calling CSR-loading functionality to the beginning of i915 driver-load
>    functionality to avoid any delay in loading.
> 4] Define another variable to track whether CSR-loading failed and use it to avoid enabling
>    DC5 if it's true.
> 5] Define CSR-load-status accessor functions for use later.
> 
> v4:
> 1] Disable DC5 before enabling PG2 instead of after it.
> 2] DC5 was being mistaken enabled even when CSR-loading timed-out. Fix that.
> 3] Enable DC5-related functionality using a macro.
> 4] Remove dc5_enabled tracking variable and its use as it's not needed now.
> 
> v5:
> 1] Mark CSR failed to load where necessary in finish_csr_load function.
> 2] Use mutex-protected accessor function to check if CSR loaded instead of directly
>    accessing the variable.
> 3] Prefix csr_load_status_get/set function names with intel_.
> 
> v6: rebase to latest.
> v7: Rebase on top of nightly (Damien)
> v8: Squashed the patch from Imre - added csr helper pointers to simplify the code. (Imre)
> v9: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)
> v10: Added a enum for different csr states, suggested by Imre. (Animesh)
> 
> v11: Based on review comments from Imre, Damien and Daniel following changes done
> - enum name chnaged to csr_state (singular form).
> - FW_UNINITIALIZED used as zeroth element in enum csr_state.
> - Prototype changed for helper function(set/get csr status), using enum csr_state instead of bool.
> 
> v12: Based on review comment from Imre, introduced bool fw_loaded local to finish_csr_load() which helps
> calling once to set the csr status. The same flag used to fail RPM if find any issue during
> firmware loading.
> 
> Issue: VIZ-2819
> Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com>
> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>

This adds some checkpatch warnings, but they are fixed later in the
patchset. As discussed earlier in the future let's avoid such rewrites
in the same patchset.

Reviewed-by: Imre Deak <imre.deak@intel.com>

> ---
>  drivers/gpu/drm/i915/i915_drv.h         |  7 ++++++
>  drivers/gpu/drm/i915/intel_csr.c        | 42 +++++++++++++++++++++++++++++++--
>  drivers/gpu/drm/i915/intel_drv.h        |  3 +++
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 33 ++++++++++++++++++++++++++
>  4 files changed, 83 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 90e47a9..670e407 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -667,6 +667,12 @@ struct intel_uncore {
>  #define for_each_fw_domain(domain__, dev_priv__, i__) \
>  	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
>  
> +enum csr_state {
> +	FW_UNINITIALIZED = 0,
> +	FW_LOADED,
> +	FW_FAILED
> +};
> +
>  struct intel_csr {
>  	const char *fw_path;
>  	__be32 *dmc_payload;
> @@ -674,6 +680,7 @@ struct intel_csr {
>  	uint32_t mmio_count;
>  	uint32_t mmioaddr[8];
>  	uint32_t mmiodata[8];
> +	enum csr_state state;
>  };
>  
>  #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
> diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
> index f5fa574..3bd29b5 100644
> --- a/drivers/gpu/drm/i915/intel_csr.c
> +++ b/drivers/gpu/drm/i915/intel_csr.c
> @@ -183,6 +183,25 @@ static char intel_get_substepping(struct drm_device *dev)
>  		return -ENODATA;
>  }
>  
> +enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv)
> +{
> +	enum csr_state state;
> +
> +	mutex_lock(&dev_priv->csr_lock);
> +	state = dev_priv->csr.state;
> +	mutex_unlock(&dev_priv->csr_lock);
> +
> +	return state;
> +}
> +
> +void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
> +			enum csr_state state)
> +{
> +	mutex_lock(&dev_priv->csr_lock);
> +	dev_priv->csr.state = state;
> +	mutex_unlock(&dev_priv->csr_lock);
> +}
> +
>  void intel_csr_load_program(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -204,6 +223,8 @@ void intel_csr_load_program(struct drm_device *dev)
>  		I915_WRITE(dev_priv->csr.mmioaddr[i],
>  			dev_priv->csr.mmiodata[i]);
>  	}
> +
> +	dev_priv->csr.state = FW_LOADED;
>  	mutex_unlock(&dev_priv->csr_lock);
>  }
>  
> @@ -220,6 +241,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  	uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
>  	uint32_t i;
>  	__be32 *dmc_payload;
> +	bool fw_loaded = false;
>  
>  	if (!fw) {
>  		i915_firmware_load_error_print(csr->fw_path, 0);
> @@ -326,7 +348,14 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  
>  	/* load csr program during system boot, as needed for DC states */
>  	intel_csr_load_program(dev);
> +	fw_loaded = true;
> +
>  out:
> +	if (fw_loaded)
> +		intel_runtime_pm_put(dev_priv);
> +	else
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> +
>  	release_firmware(fw);
>  }
>  
> @@ -343,17 +372,25 @@ void intel_csr_ucode_init(struct drm_device *dev)
>  		csr->fw_path = I915_CSR_SKL;
>  	else {
>  		DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>  		return;
>  	}
>  
> +	/*
> +	 * Obtain a runtime pm reference, until CSR is loaded,
> +	 * to avoid entering runtime-suspend.
> +	 */
> +	intel_runtime_pm_get(dev_priv);
> +
>  	/* CSR supported for platform, load firmware */
>  	ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path,
>  				&dev_priv->dev->pdev->dev,
>  				GFP_KERNEL, dev_priv,
>  				finish_csr_load);
> -	if (ret)
> +	if (ret) {
>  		i915_firmware_load_error_print(csr->fw_path, ret);
> -
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> +	}
>  }
>  
>  void intel_csr_ucode_fini(struct drm_device *dev)
> @@ -363,5 +400,6 @@ void intel_csr_ucode_fini(struct drm_device *dev)
>  	if (!HAS_CSR(dev))
>  		return;
>  
> +	intel_csr_load_status_set(dev_priv, FW_FAILED);
>  	kfree(dev_priv->csr.dmc_payload);
>  }
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index f3a2d88..25d7956 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1064,6 +1064,9 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
>  
>  /* intel_csr.c */
>  void intel_csr_ucode_init(struct drm_device *dev);
> +enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv);
> +void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
> +					enum csr_state state);
>  void intel_csr_load_program(struct drm_device *dev);
>  void intel_csr_ucode_fini(struct drm_device *dev);
>  
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index ce00e69..23f02a8 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -49,6 +49,8 @@
>   * present for a given platform.
>   */
>  
> +#define GEN9_ENABLE_DC5(dev) (IS_SKYLAKE(dev))
> +
>  #define for_each_power_well(i, power_well, domain_mask, power_domains)	\
>  	for (i = 0;							\
>  	     i < (power_domains)->power_well_count &&			\
> @@ -319,9 +321,20 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
>  	SKL_DISPLAY_MISC_IO_POWER_DOMAINS)) |		\
>  	BIT(POWER_DOMAIN_INIT))
>  
> +static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
> +{
> +	/* TODO: Implementation to be done. */
> +}
> +
> +static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
> +{
> +	/* TODO: Implementation to be done. */
> +}
> +
>  static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  			struct i915_power_well *power_well, bool enable)
>  {
> +	struct drm_device *dev = dev_priv->dev;
>  	uint32_t tmp, fuse_status;
>  	uint32_t req_mask, state_mask;
>  	bool is_enabled, enable_requested, check_fuse_status = false;
> @@ -361,6 +374,13 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  
>  	if (enable) {
>  		if (!enable_requested) {
> +			WARN((tmp & state_mask) &&
> +				!I915_READ(HSW_PWR_WELL_BIOS),
> +				"Invalid for power well status to be enabled, unless done by the BIOS, \
> +				when request is to disable!\n");
> +			if (GEN9_ENABLE_DC5(dev) &&
> +				power_well->data == SKL_DISP_PW_2)
> +				gen9_disable_dc5(dev_priv);
>  			I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask);
>  		}
>  
> @@ -377,6 +397,19 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  			I915_WRITE(HSW_PWR_WELL_DRIVER,	tmp & ~req_mask);
>  			POSTING_READ(HSW_PWR_WELL_DRIVER);
>  			DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
> +
> +			if (GEN9_ENABLE_DC5(dev) &&
> +				power_well->data == SKL_DISP_PW_2) {
> +				enum csr_state state;
> +
> +				wait_for((state = intel_csr_load_status_get(dev_priv)) !=
> +						FW_UNINITIALIZED, 1000);
> +				if (state != FW_LOADED)
> +					DRM_ERROR("CSR firmware not ready (%d)\n",
> +							state);
> +				else
> +					gen9_enable_dc5(dev_priv);
> +			}
>  		}
>  	}
>  


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

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

* Re: [PATCH v4 3/8] drm/i915/skl: Implement enable/disable for Display C5 state.
  2015-04-16  8:52 ` [PATCH v4 3/8] drm/i915/skl: Implement enable/disable for Display C5 state Animesh Manna
@ 2015-04-30 13:21   ` Imre Deak
  0 siblings, 0 replies; 37+ messages in thread
From: Imre Deak @ 2015-04-30 13:21 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx

On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
> From: "A.Sunil Kamath" <sunil.kamath@intel.com>
> 
> This patch just implements the basic enable and disable
> functions of DC5 state which is needed for both SKL and BXT.
> 
> Its important to load respective CSR program before calling
> enable, which anyways will happen as CSR program is executed
> during boot.
> 
> DC5 is a power saving state where hardware dynamically disables
> power well 1 and the CDCLK PLL and saves the associated registers.
> 
> DC5 can be entered when software allows it, power well 2 is
> disabled, and hardware detects that all pipes are disabled
> or pipe A is enabled with PSR active.
> 
> Its better to configure display engine to have power well 2 disabled before
> getting into DC5 enable function. Hence rpm framework will have to
> ensure to check status of power well 2 before calling gen9_enable_dc5.
> 
> Rather dc5 entry criteria should be decided based on power well 2 status.
> If disabled, then call gen9_enable_dc5.
> 
> v2: Replace HAS_ with IS_ check as per Daniel's review comments
> 
> v3: Cleared the bits dc5/dc6 enable of DC_STATE_EN register
> before setting them as per Satheesh's review comments.
> 
> v4: call POSTING_READ for every write to a register to ensure that
> its written immediately.
> 
> v5: Modified as per review comments from Imre.
> - Squashed register definitions into this patch.
> - Finetuned comments and functions.
> 
> v6:
> Avoid redundant writes in gen9_set_dc_state_debugmask_memory_up function.
> 
> v7:
> 1] Rebase to latest.
> 2] Move all runtime PM functions defined in intel_display.c to
>    intel_runtime_pm.c.
> 
> v8: Rebased to drm-intel-nightly. (Animesh)
> 
> Issue: VIZ-2819
> Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>

Reviewed-by: Imre Deak <imre.deak@intel.com>

> ---
>  drivers/gpu/drm/i915/i915_reg.h         | 11 +++++++++
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 41 +++++++++++++++++++++++++++++++--
>  2 files changed, 50 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 596e8eb..dcb8528 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -6792,6 +6792,17 @@ enum skl_disp_power_wells {
>  #define GET_CFG_CR1_REG(id) (DPLL1_CFGCR1 + (id - SKL_DPLL1) * 8)
>  #define GET_CFG_CR2_REG(id) (DPLL1_CFGCR2 + (id - SKL_DPLL1) * 8)
>  
> +/*
> +* SKL DC
> +*/
> +#define  DC_STATE_EN			0x45504
> +#define  DC_STATE_EN_UPTO_DC5		(1<<0)
> +#define  DC_STATE_EN_UPTO_DC6		(2<<0)
> +#define  DC_STATE_EN_UPTO_DC5_DC6_MASK   0x3
> +
> +#define  DC_STATE_DEBUG                  0x45520
> +#define  DC_STATE_DEBUG_MASK_MEMORY_UP	(1<<1)
> +
>  /* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this register,
>   * since on HSW we can't write to it using I915_WRITE. */
>  #define D_COMP_HSW			(MCHBAR_MIRROR_BASE_SNB + 0x5F0C)
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 23f02a8..466ea69 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -321,14 +321,51 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
>  	SKL_DISPLAY_MISC_IO_POWER_DOMAINS)) |		\
>  	BIT(POWER_DOMAIN_INIT))
>  
> +static void gen9_set_dc_state_debugmask_memory_up(
> +			struct drm_i915_private *dev_priv)
> +{
> +	uint32_t val;
> +
> +	/* The below bit doesn't need to be cleared ever afterwards */
> +	val = I915_READ(DC_STATE_DEBUG);
> +	if (!(val & DC_STATE_DEBUG_MASK_MEMORY_UP)) {
> +		val |= DC_STATE_DEBUG_MASK_MEMORY_UP;
> +		I915_WRITE(DC_STATE_DEBUG, val);
> +		POSTING_READ(DC_STATE_DEBUG);
> +	}
> +}
> +
>  static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
>  {
> -	/* TODO: Implementation to be done. */
> +	struct drm_device *dev = dev_priv->dev;
> +	uint32_t val;
> +
> +	WARN_ON(!IS_GEN9(dev));
> +
> +	DRM_DEBUG_KMS("Enabling DC5\n");
> +
> +	gen9_set_dc_state_debugmask_memory_up(dev_priv);
> +
> +	val = I915_READ(DC_STATE_EN);
> +	val &= ~DC_STATE_EN_UPTO_DC5_DC6_MASK;
> +	val |= DC_STATE_EN_UPTO_DC5;
> +	I915_WRITE(DC_STATE_EN, val);
> +	POSTING_READ(DC_STATE_EN);
>  }
>  
>  static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
>  {
> -	/* TODO: Implementation to be done. */
> +	struct drm_device *dev = dev_priv->dev;
> +	uint32_t val;
> +
> +	WARN_ON(!IS_GEN9(dev));
> +
> +	DRM_DEBUG_KMS("Disabling DC5\n");
> +
> +	val = I915_READ(DC_STATE_EN);
> +	val &= ~DC_STATE_EN_UPTO_DC5;
> +	I915_WRITE(DC_STATE_EN, val);
> +	POSTING_READ(DC_STATE_EN);
>  }
>  
>  static void skl_set_power_well(struct drm_i915_private *dev_priv,


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

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

* Re: [PATCH v4 4/8] drm/i915/skl: Assert the requirements to enter or exit DC5.
  2015-04-16  8:52 ` [PATCH v4 4/8] drm/i915/skl: Assert the requirements to enter or exit DC5 Animesh Manna
@ 2015-04-30 13:26   ` Imre Deak
  0 siblings, 0 replies; 37+ messages in thread
From: Imre Deak @ 2015-04-30 13:26 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
> From: Suketu Shah <suketu.j.shah@intel.com>
> 
> Warn if the conditions to enter or exit DC5 are not satisfied such
> as support for runtime PM, state of power well, CSR loading etc.
> 
> v2: Removed camelcase in functions and variables.
> 
> v3: Do some minimal check to assert if CSR program is not loaded.
> 
> v4:
> 1] Used an appropriate function lookup_power_well() to identify power well,
> instead of using a magic number which can change in future.
> 2] Split the conditions further in assert_can_enable_DC5() and added more checks.
> 3] Removed all WARNs from assert_can_disable_DC5 as they were unnecessary and added two
>    new ones.
> 4] Changed variable names as updated in earlier patches.
> 
> v5:
> 1] Change lookup_power_well function to take an int power well id.
> 2] Define a new intel_display_power_well_is_enabled helper function to check whether a
>    particular power well is enabled.
> 3] Use CSR-related mutex in assert_csr_loaded function.
> 
> v6: Remove use of dc5_enabled variable as it's no longer needed.
> 
> v7:
> 1] Rebase to latest.
> 2] Move all DC5-related functions from intel_display.c to intel_runtime_pm.c.
> 
> v8: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)
> 
> v9: Modified below changes based on review comments from Imre.
> - Moved intel_display_power_well_is_enabled() to intel_runtime_pm.c.
> - Removed mutex lock from assert_csr_loaded(). (Animesh)
> 
> Issue: VIZ-2819
> Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com>
> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>

Reviewed-by: Imre Deak <imre.deak@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_csr.c        |  9 ++++++
>  drivers/gpu/drm/i915/intel_drv.h        |  1 +
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 51 +++++++++++++++++++++++++++++----
>  3 files changed, 56 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
> index fe6789f..d58effe 100644
> --- a/drivers/gpu/drm/i915/intel_csr.c
> +++ b/drivers/gpu/drm/i915/intel_csr.c
> @@ -410,3 +410,12 @@ void intel_csr_ucode_fini(struct drm_device *dev)
>  	intel_csr_load_status_set(dev_priv, FW_FAILED);
>  	kfree(dev_priv->csr.dmc_payload);
>  }
> +
> +void assert_csr_loaded(struct drm_i915_private *dev_priv)
> +{
> +	WARN((intel_csr_load_status_get(dev_priv) != FW_LOADED), "CSR is not loaded.\n");
> +	WARN(!I915_READ(CSR_PROGRAM_BASE),
> +				"CSR program storage start is NULL\n");
> +	WARN(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n");
> +	WARN(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n");
> +}
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 25d7956..2eb0169 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1069,6 +1069,7 @@ void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
>  					enum csr_state state);
>  void intel_csr_load_program(struct drm_device *dev);
>  void intel_csr_ucode_fini(struct drm_device *dev);
> +void assert_csr_loaded(struct drm_i915_private *dev_priv);
>  
>  /* intel_dp.c */
>  void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 466ea69..da8c18d 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -64,6 +64,9 @@
>  	     i--)							 \
>  		if ((power_well)->domains & (domain_mask))
>  
> +bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
> +				    int power_well_id);
> +
>  /*
>   * We should only use the power well if we explicitly asked the hardware to
>   * enable it, so check if it's enabled and also check if we've requested it to
> @@ -335,12 +338,39 @@ static void gen9_set_dc_state_debugmask_memory_up(
>  	}
>  }
>  
> -static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
> +static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
>  {
>  	struct drm_device *dev = dev_priv->dev;
> +	bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv,
> +					SKL_DISP_PW_2);
> +
> +	WARN(!IS_SKYLAKE(dev), "Platform doesn't support DC5.\n");
> +	WARN(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n");
> +	WARN(pg2_enabled, "PG2 not disabled to enable DC5.\n");
> +
> +	WARN((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5),
> +				"DC5 already programmed to be enabled.\n");
> +	WARN(dev_priv->pm.suspended,
> +		"DC5 cannot be enabled, if platform is runtime-suspended.\n");
> +
> +	assert_csr_loaded(dev_priv);
> +}
> +
> +static void assert_can_disable_dc5(struct drm_i915_private *dev_priv)
> +{
> +	bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv,
> +					SKL_DISP_PW_2);
> +
> +	WARN(!pg2_enabled, "PG2 not enabled to disable DC5.\n");
> +	WARN(dev_priv->pm.suspended,
> +		"Disabling of DC5 while platform is runtime-suspended should never happen.\n");
> +}
> +
> +static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
> +{
>  	uint32_t val;
>  
> -	WARN_ON(!IS_GEN9(dev));
> +	assert_can_enable_dc5(dev_priv);
>  
>  	DRM_DEBUG_KMS("Enabling DC5\n");
>  
> @@ -355,10 +385,9 @@ static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
>  
>  static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_device *dev = dev_priv->dev;
>  	uint32_t val;
>  
> -	WARN_ON(!IS_GEN9(dev));
> +	assert_can_disable_dc5(dev_priv);
>  
>  	DRM_DEBUG_KMS("Disabling DC5\n");
>  
> @@ -1318,7 +1347,7 @@ static struct i915_power_well chv_power_wells[] = {
>  };
>  
>  static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv,
> -						 enum punit_power_well power_well_id)
> +						 int power_well_id)
>  {
>  	struct i915_power_domains *power_domains = &dev_priv->power_domains;
>  	struct i915_power_well *power_well;
> @@ -1332,6 +1361,18 @@ static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_pr
>  	return NULL;
>  }
>  
> +bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
> +				    int power_well_id)
> +{
> +	struct i915_power_well *power_well;
> +	bool ret;
> +
> +	power_well = lookup_power_well(dev_priv, power_well_id);
> +	ret = power_well->ops->is_enabled(dev_priv, power_well);
> +
> +	return ret;
> +}
> +
>  static struct i915_power_well skl_power_wells[] = {
>  	{
>  		.name = "always-on",


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

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

* Re: [PATCH v4 5/8] drm/i915/skl: Add DC6 Trigger sequence.
  2015-04-16  8:52 ` [PATCH v4 5/8] drm/i915/skl: Add DC6 Trigger sequence Animesh Manna
@ 2015-04-30 13:41   ` Imre Deak
  2015-05-04  9:44   ` Daniel Vetter
  2015-05-04 13:05   ` Daniel Vetter
  2 siblings, 0 replies; 37+ messages in thread
From: Imre Deak @ 2015-04-30 13:41 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
> From: Suketu Shah <suketu.j.shah@intel.com>
> 
> Add triggers for DC6 as per details provided in skl_enable_dc6
> and skl_disable_dc6 implementations.
> 
> Also Call POSTING_READ for every write to a register to ensure
> it is written to immediately
> 
> v1: Remove POSTING_READ and intel_prepare_ddi calls as they've been added in previous patches.
> 
> v2:
> 1] Remove check for backlight disabled as it should be the case by that time.
> 2] Mark DC5 as disabled when enabling DC6.
> 3] Return from DC5-disabling function early if DC5 is already be disabled which can happen
>    due to DC6-enabling earlier.
> 3] Ensure CSR firmware is loaded after resume from DC6 as corresponding memory contents won't
>    be retained after runtime-suspend.
> 4] Ensure that CSR isn't identified as loaded before CSR-loading program is called during
>    runtime-resume.
> 
> v3: Rebase to latest
> Modified as per review comments from Imre and after discussion with Art:
> 1] DC6 should be preferably enabled when PG2 is disabled by SW as the check for PG1 being
>    disabled is taken of by HW to enter DC6, and disabled when PG2 is enabled respectively.
>    This helps save more power, especially in the case when display is disabled but GT is
>    enabled. Accordingly, replacing DC5 trigger sequence with DC6 for SKL.
> 2] DC6 could be enabled from intel_runtime_suspend() function, if DC5 is already enabled.
> 3] Move CSR-load-status setting code from intel_runtime_suspend function to a new function.
> 
> v4:
> 1] Enable/disable DC6 only when toggling the power-well using a newly defined macro ENABLE_DC6.
> 
> v5:
> 1] Load CSR on system resume too as firmware may be lost on system suspend preventing
>    enabling DC5, DC6.
> 2] DDI buffers shouldn't be programmed during driver-load/resume as it's already done
>    during modeset initialization then and also that the encoder list is still uninitialized by
>    then. Therefore, call intel_prepare_ddi function right after disabling DC6 but outside
>    skl_disable_dc6 function and not during driver-load/resume.
> 
> v6:
> 1] Rebase to latest.
> 2] Move SKL_ENABLE_DC6 macro definition from intel_display.c to intel_runtime_pm.c.
> 
> v7:
> 1) Refactored the code for removing the warning got from checkpatch.
> 2) After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)
> 
> v8:
> - Reverted the changes done in v7.
> - Removed the condition check in skl_prepare_resune(). (Animesh)
> 
> Issue: VIZ-2819
> Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com>
> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c         | 30 +++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 43 +++++++++++++++++++++++++++------
>  2 files changed, 66 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index acd0e2b..0f590e3 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -594,6 +594,8 @@ static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
>  static int intel_suspend_complete(struct drm_i915_private *dev_priv);
>  static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
>  			      bool rpm_resume);
> +static int skl_resume_prepare(struct drm_i915_private *dev_priv);
> +
>  
>  static int i915_drm_suspend(struct drm_device *dev)
>  {
> @@ -808,6 +810,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
>  
>  	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
>  		hsw_disable_pc8(dev_priv);
> +	else if (IS_SKYLAKE(dev_priv))
> +		ret = skl_resume_prepare(dev_priv);
>  
>  	intel_uncore_sanitize(dev);
>  	intel_power_domains_init_hw(dev_priv);
> @@ -1022,6 +1026,19 @@ static int i915_pm_resume(struct device *dev)
>  	return i915_drm_resume(drm_dev);
>  }
>  
> +static int skl_suspend_complete(struct drm_i915_private *dev_priv)
> +{
> +	/* Enabling DC6 is not a hard requirement to enter runtime D3 */
> +
> +	/*
> +	 * This is to ensure that CSR isn't identified as loaded before
> +	 * CSR-loading program is called during runtime-resume.
> +	 */
> +	intel_csr_load_status_set(dev_priv, FW_UNINITIALIZED);
> +
> +	return 0;
> +}
> +
>  static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
>  {
>  	hsw_enable_pc8(dev_priv);
> @@ -1029,6 +1046,15 @@ static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
>  	return 0;
>  }
>  
> +static int skl_resume_prepare(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +
> +	intel_csr_load_program(dev);
> +
> +	return 0;
> +}
> +
>  /*
>   * Save all Gunit registers that may be lost after a D3 and a subsequent
>   * S0i[R123] transition. The list of registers needing a save/restore is
> @@ -1487,6 +1513,8 @@ static int intel_runtime_resume(struct device *device)
>  
>  	if (IS_GEN6(dev_priv))
>  		intel_init_pch_refclk(dev);
> +	else if (IS_SKYLAKE(dev))
> +		ret = skl_resume_prepare(dev_priv);

This needs to be rebased on the recent BXT changes. While at it please
fix the IS_SKYLAKE check to be an 'else if' condition as above for
consistency (botched in the BXT series and missed in my review).

>  	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
>  		hsw_disable_pc8(dev_priv);
>  	else if (IS_VALLEYVIEW(dev_priv))
> @@ -1519,6 +1547,8 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv)
>  	struct drm_device *dev = dev_priv->dev;
>  	int ret;
>  
> +	if (IS_SKYLAKE(dev))
> +		ret = skl_suspend_complete(dev_priv);
>  	if (IS_HASWELL(dev) || IS_BROADWELL(dev))

This needs to be rebased as above and the 'else if' ladder kept for
consistency.

With the above fixed this is:
Reviewed-by: Imre Deak <imre.deak@intel.com>

>  		ret = hsw_suspend_complete(dev_priv);
>  	else if (IS_VALLEYVIEW(dev))
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index da8c18d..7e6908e 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -49,7 +49,8 @@
>   * present for a given platform.
>   */
>  
> -#define GEN9_ENABLE_DC5(dev) (IS_SKYLAKE(dev))
> +#define GEN9_ENABLE_DC5(dev) 0
> +#define SKL_ENABLE_DC6(dev) IS_SKYLAKE(dev)
>  
>  #define for_each_power_well(i, power_well, domain_mask, power_domains)	\
>  	for (i = 0;							\
> @@ -397,6 +398,16 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
>  	POSTING_READ(DC_STATE_EN);
>  }
>  
> +static void skl_enable_dc6(struct drm_i915_private *dev_priv)
> +{
> +	/* TODO: Implementation to be done. */
> +}
> +
> +static void skl_disable_dc6(struct drm_i915_private *dev_priv)
> +{
> +	/* TODO: Implementation to be done. */
> +}
> +
>  static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  			struct i915_power_well *power_well, bool enable)
>  {
> @@ -444,9 +455,21 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  				!I915_READ(HSW_PWR_WELL_BIOS),
>  				"Invalid for power well status to be enabled, unless done by the BIOS, \
>  				when request is to disable!\n");
> -			if (GEN9_ENABLE_DC5(dev) &&
> -				power_well->data == SKL_DISP_PW_2)
> -				gen9_disable_dc5(dev_priv);
> +			if ((GEN9_ENABLE_DC5(dev) || SKL_ENABLE_DC6(dev)) &&
> +				power_well->data == SKL_DISP_PW_2) {
> +				if (SKL_ENABLE_DC6(dev)) {
> +					skl_disable_dc6(dev_priv);
> +					/*
> +					 * DDI buffer programming unnecessary during driver-load/resume
> +					 * as it's already done during modeset initialization then.
> +					 * It's also invalid here as encoder list is still uninitialized.
> +					 */
> +					if (!dev_priv->power_domains.initializing)
> +						intel_prepare_ddi(dev);
> +				} else {
> +					gen9_disable_dc5(dev_priv);
> +				}
> +			}
>  			I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask);
>  		}
>  
> @@ -464,17 +487,23 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  			POSTING_READ(HSW_PWR_WELL_DRIVER);
>  			DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
>  
> -			if (GEN9_ENABLE_DC5(dev) &&
> +			if ((GEN9_ENABLE_DC5(dev) || SKL_ENABLE_DC6(dev)) &&
>  				power_well->data == SKL_DISP_PW_2) {
>  				enum csr_state state;
> -
> +				/* TODO: wait for a completion event or
> +				 * similar here instead of busy
> +				 * waiting using wait_for function.
> +				 */
>  				wait_for((state = intel_csr_load_status_get(dev_priv)) !=
>  						FW_UNINITIALIZED, 1000);
>  				if (state != FW_LOADED)
>  					DRM_ERROR("CSR firmware not ready (%d)\n",
>  							state);
>  				else
> -					gen9_enable_dc5(dev_priv);
> +					if (SKL_ENABLE_DC6(dev))
> +						skl_enable_dc6(dev_priv);
> +					else
> +						gen9_enable_dc5(dev_priv);
>  			}
>  		}
>  	}


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

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

* Re: [PATCH v4 6/8] Implement enable/disable for Display C6 state
  2015-04-16  8:52 ` [PATCH v4 6/8] Implement enable/disable for Display C6 state Animesh Manna
@ 2015-04-30 13:45   ` Imre Deak
  0 siblings, 0 replies; 37+ messages in thread
From: Imre Deak @ 2015-04-30 13:45 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx

On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
> From: "A.Sunil Kamath" <sunil.kamath@intel.com>
> 
> This patch just implements the basic enable and disable
> functions of DC6 state which is needed for SKL platform.
> 
> Its important to load SKL CSR program before calling enable.
> 
> DC6 is a deeper power saving state where hardware dynamically
> disables power well 0 and saves the associated registers.
> DC6 can be entered when software allows it, the conditions
> for DC5 are met, and the PCU allows DC6.
> DC6 cannot be used if the backlight is being driven from the
> display utility pin.
> 
> Its better to configure display engine to have power well 2
> disabled before getting into DC6 enable function. Hence rpm
> framework will ensure to check status of power well 2 and DC5
> before calling skl_enable_dc6.
> 
> v2: Replace HAS_ with IS_ check as per Daniel's review comments
> 
> v3: Cleared the bits dc5/dc6 enable of DC_STATE_EN register
> before setting them as per Satheesh's review comments.
> 
> v4: No need to call gen9_disable_dc5 inside enable sequence of
> DC6, as its already take care above.
> 
> v5: call POSTING_READ for every write to a register to ensure that
> its written immediately.
> Call intel_prepare_ddi during DC6 exit as it's required on low-power exit.
> 
> v6: Protect DC6-enabling-disabling functionality with locks to synchronize
> with CSR-loading code.
> 
> v7: Remove grabbing CSR-related mutex in skl_enable/disable_dc6 functions as
>     deferred DC5-enabling functionality is now removed.
> 
> v8: Remove 'Disabling DC5' from the debug comment during DC6 enabling as when
>     DC6 is allowed, DC5 is not programmed at all.
> 
> v9:
> 1] Rebase to latest.
> 2] Move all DC6-related functions from intel_display.c to intel_runtime_pm.c.
> 
> v10: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)
> 
> Issue: VIZ-2819
> Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>

Reviewed-by: Imre Deak <imre.deak@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 27 +++++++++++++++++++++++++--
>  1 file changed, 25 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 7e6908e..ba49795 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -400,12 +400,35 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
>  
>  static void skl_enable_dc6(struct drm_i915_private *dev_priv)
>  {
> -	/* TODO: Implementation to be done. */
> +	struct drm_device *dev = dev_priv->dev;
> +	uint32_t val;
> +
> +	WARN_ON(!IS_SKYLAKE(dev));
> +
> +	DRM_DEBUG_KMS("Enabling DC6\n");
> +
> +	gen9_set_dc_state_debugmask_memory_up(dev_priv);
> +
> +	val = I915_READ(DC_STATE_EN);
> +	val &= ~DC_STATE_EN_UPTO_DC5_DC6_MASK;
> +	val |= DC_STATE_EN_UPTO_DC6;
> +	I915_WRITE(DC_STATE_EN, val);
> +	POSTING_READ(DC_STATE_EN);
>  }
>  
>  static void skl_disable_dc6(struct drm_i915_private *dev_priv)
>  {
> -	/* TODO: Implementation to be done. */
> +	struct drm_device *dev = dev_priv->dev;
> +	uint32_t val;
> +
> +	WARN_ON(!IS_SKYLAKE(dev));
> +
> +	DRM_DEBUG_KMS("Disabling DC6\n");
> +
> +	val = I915_READ(DC_STATE_EN);
> +	val &= ~DC_STATE_EN_UPTO_DC6;
> +	I915_WRITE(DC_STATE_EN, val);
> +	POSTING_READ(DC_STATE_EN);
>  }
>  
>  static void skl_set_power_well(struct drm_i915_private *dev_priv,


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

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

* Re: [PATCH v4 8/8] drm/i915/skl: Enable runtime PM
  2015-04-16  8:52 ` [PATCH v4 8/8] drm/i915/skl: Enable runtime PM Animesh Manna
  2015-04-17  1:52   ` shuang.he
@ 2015-04-30 13:47   ` Imre Deak
  1 sibling, 0 replies; 37+ messages in thread
From: Imre Deak @ 2015-04-30 13:47 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On to, 2015-04-16 at 14:22 +0530, Animesh Manna wrote:
> From: Suketu Shah <suketu.j.shah@intel.com>
> 
> Enable runtime PM for Skylake platform
> 
> v2: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)
> 
> Issue: VIZ-2819
> Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com>
> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>

Reviewed-by: Imre Deak <imre.deak@intel.com>

> ---
>  drivers/gpu/drm/i915/i915_drv.h | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 670e407..e8d27eb 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2442,7 +2442,8 @@ struct drm_i915_cmd_table {
>  				 IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || \
>  				 IS_SKYLAKE(dev))
>  #define HAS_RUNTIME_PM(dev)	(IS_GEN6(dev) || IS_HASWELL(dev) || \
> -				 IS_BROADWELL(dev) || IS_VALLEYVIEW(dev))
> +				 IS_BROADWELL(dev) || IS_VALLEYVIEW(dev) || \
> +				 IS_SKYLAKE(dev))
>  #define HAS_RC6(dev)		(INTEL_INFO(dev)->gen >= 6)
>  #define HAS_RC6p(dev)		(INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
>  


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

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

* Re: [PATCH v5 1/8] drm/i915/skl: Add support to load SKL CSR firmware.
  2015-04-30 13:02       ` Imre Deak
@ 2015-05-04  9:30         ` Daniel Vetter
  2015-05-04 10:31           ` Imre Deak
  0 siblings, 1 reply; 37+ messages in thread
From: Daniel Vetter @ 2015-05-04  9:30 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Apr 30, 2015 at 04:02:34PM +0300, Imre Deak wrote:
> On ke, 2015-04-29 at 22:59 +0530, Animesh Manna wrote:
> > From: "A.Sunil Kamath" <sunil.kamath@intel.com>
> > 
> > Display Context Save and Restore support is needed for
> > various SKL Display C states like DC5, DC6.
> > 
> > This implementation is added based on first version of DMC CSR program
> > that we received from h/w team.
> > 
> > Here we are using request_firmware based design.
> > Finally this firmware should end up in linux-firmware tree.
> > 
> > For SKL platform its mandatory to ensure that we load this
> > csr program before enabling DC states like DC5/DC6.
> > 
> > As CSR program gets reset on various conditions, we should ensure
> > to load it during boot and in future change to be added to load
> > this system resume sequence too.
> > 
> > v1: Initial relese as RFC patch
> > 
> > v2: Design change as per Daniel, Damien and Shobit's review comments
> > request firmware method followed.
> > 
> > v3: Some optimization and functional changes.
> > Pulled register defines into drivers/gpu/drm/i915/i915_reg.h
> > Used kmemdup to allocate and duplicate firmware content.
> > Ensured to free allocated buffer.
> > 
> > v4: Modified as per review comments from Satheesh and Daniel
> > Removed temporary buffer.
> > Optimized number of writes by replacing I915_WRITE with I915_WRITE64.
> > 
> > v5:
> > Modified as per review comemnts from Damien.
> > - Changed name for functions and firmware.
> > - Introduced HAS_CSR.
> > - Reverted back previous change and used csr_buf with u8 size.
> > - Using cpu_to_be64 for endianness change.
> > 
> > Modified as per review comments from Imre.
> > - Modified registers and macro names to be a bit closer to bspec terminology
> > and the existing register naming in the driver.
> > - Early return for non SKL platforms in intel_load_csr_program function.
> > - Added locking around CSR program load function as it may be called
> > concurrently during system/runtime resume.
> > - Releasing the fw before loading the program for consistency
> > - Handled error path during f/w load.
> > 
> > v6: Modified as per review comments from Imre.
> > - Corrected out_freecsr sequence.
> > 
> > v7: Modified as per review comments from Imre.
> > Fail loading fw if fw->size%8!=0.
> > 
> > v8: Rebase to latest.
> > 
> > v9: Rebase on top of -nightly (Damien)
> > 
> > v10: Enabled support for dmc firmware ver 1.0.
> > According to ver 1.0 in a single binary package all the firmware's that are
> > required for different stepping's of the product will be stored. The package
> > contains the css header, followed by the package header and the actual dmc
> > firmwares. Package header contains the firmware/stepping mapping table and
> > the corresponding firmware offsets to the individual binaries, within the
> > package. Each individual program binary contains the header and the payload
> > sections whose size is specified in the header section. This changes are done
> > to extract the specific firmaware from the package. (Animesh)
> > 
> > v11: Modified as per review comemnts from Imre.
> > - Added code comment from bpec for header structure elements.
> > - Added __packed to avoid structure padding.
> > - Added helper functions for stepping and substepping info.
> > - Added code comment for CSR_MAX_FW_SIZE.
> > - Disabled BXT firmware loading, will be enabled with dmc 1.0 support.
> > - Changed skl_stepping_info based on bspec, earlier used from config DB.
> > - Removed duplicate call of cpu_to_be* from intel_csr_load_program function.
> > - Used cpu_to_be32 instead of cpu_to_be64 as firmware binary in dword aligned.
> > - Added sanity check for header length.
> > - Added sanity check for mmio address got from firmware binary.
> > - kmalloc done separately for dmc header and dmc firmware. (Animesh)
> > 
> > v12: Modified as per review comemnts from Imre.
> > - Corrected the typo error in skl stepping info structure.
> > - Added out-of-bound access for skl_stepping_info.
> > - Sanity check for mmio address modified.
> > - Sanity check added for stepping and substeppig.
> > - Modified the intel_dmc_info structure, cache only the required header info. (Animesh)
> > 
> > v13: clarify firmware load error message.
> > The reason for a firmware loading failure can be obscure if the driver
> > is built-in. Provide an explanation to the user about the likely reason for
> > the failure and how to resolve it. (Imre)
> > 
> > v14: Suggested by Jani.
> > - fix s/I915/CONFIG_DRM_I915/ typo
> > - add fw_path to the firmware object instead of using a static ptr (Jani)
> > 
> > v15:
> > 1) Changed the firmware name as dmc_gen9.bin, everytime for a new firmware version a symbolic link
> > with same name will help not to build kernel again.
> > 2) Changes done as per review comments from Imre.
> > - Error check removed for intel_csr_ucode_init.
> > - Moved csr-specific data structure to intel_csr.h and optimization done on structure definition.
> > - fw->data used directly for parsing the header info & memory allocation
> > only done separately for payload. (Animesh)
> > 
> > v16:
> > - No need for out_regs label in i915_driver_load(), so removed it.
> > - Changed the firmware name as skl_dmc_ver1.bin, followed naming convention <platform>_dmc_<api-version>.bin (Animesh)
> > 
> > Issue: VIZ-2569
> > Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
> > Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> > Signed-off-by: Animesh Manna <animesh.manna@intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> 
> For the future: scripts/checkpatch.pl has a valid warning about the
> commit message, please fix the issues reported by this tool next time.

Hm, what does checkpatch complain about - mine didn't? I did apply the
patch manually though.
-Daniel

> 
> Reviewed-by: Imre Deak <imre.deak@intel.com>
> 
> > ---
> >  drivers/gpu/drm/i915/Makefile    |   3 +-
> >  drivers/gpu/drm/i915/i915_dma.c  |  11 +-
> >  drivers/gpu/drm/i915/i915_drv.c  |  20 +++
> >  drivers/gpu/drm/i915/i915_drv.h  |  17 ++
> >  drivers/gpu/drm/i915/intel_csr.c | 367 +++++++++++++++++++++++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_drv.h |   5 +
> >  6 files changed, 420 insertions(+), 3 deletions(-)
> >  create mode 100644 drivers/gpu/drm/i915/intel_csr.c
> > 
> > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> > index a69002e..5238deb 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_csr.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 e44116f..a238889 100644
> > --- a/drivers/gpu/drm/i915/i915_dma.c
> > +++ b/drivers/gpu/drm/i915/i915_dma.c
> > @@ -816,6 +816,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
> >  	spin_lock_init(&dev_priv->mmio_flip_lock);
> >  	mutex_init(&dev_priv->dpio_lock);
> >  	mutex_init(&dev_priv->modeset_restore_lock);
> > +	mutex_init(&dev_priv->csr_lock);
> >  
> >  	intel_pm_setup(dev);
> >  
> > @@ -861,9 +862,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
> >  
> >  	intel_uncore_init(dev);
> >  
> > +	/* Load CSR Firmware for SKL */
> > +	intel_csr_ucode_init(dev);
> > +
> >  	ret = i915_gem_gtt_init(dev);
> >  	if (ret)
> > -		goto out_regs;
> > +		goto out_freecsr;
> >  
> >  	/* WARNING: Apparently we must kick fbdev drivers before vgacon,
> >  	 * otherwise the vga fbdev driver falls over. */
> > @@ -1033,7 +1037,8 @@ out_mtrrfree:
> >  	io_mapping_free(dev_priv->gtt.mappable);
> >  out_gtt:
> >  	i915_global_gtt_cleanup(dev);
> > -out_regs:
> > +out_freecsr:
> > +	intel_csr_ucode_fini(dev);
> >  	intel_uncore_fini(dev);
> >  	pci_iounmap(dev->pdev, dev_priv->regs);
> >  put_bridge:
> > @@ -1113,6 +1118,8 @@ int i915_driver_unload(struct drm_device *dev)
> >  	mutex_unlock(&dev->struct_mutex);
> >  	i915_gem_cleanup_stolen(dev);
> >  
> > +	intel_csr_ucode_fini(dev);
> > +
> >  	intel_teardown_gmbus(dev);
> >  	intel_teardown_mchbar(dev);
> >  
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > index c3fdbb0..acd0e2b 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -556,6 +556,26 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
> >  	cancel_delayed_work_sync(&dev_priv->hotplug_reenable_work);
> >  }
> >  
> > +void i915_firmware_load_error_print(const char *fw_path, int err)
> > +{
> > +	DRM_ERROR("failed to load firmware %s (%d)\n", fw_path, err);
> > +
> > +	/*
> > +	 * If the reason is not known assume -ENOENT since that's the most
> > +	 * usual failure mode.
> > +	 */
> > +	if (!err)
> > +		err = -ENOENT;
> > +
> > +	if (!(IS_BUILTIN(CONFIG_DRM_I915) && err == -ENOENT))
> > +		return;
> > +
> > +	DRM_ERROR(
> > +	  "The driver is built-in, so to load the firmware you need to\n"
> > +	  "include it either in the kernel (see CONFIG_EXTRA_FIRMWARE) or\n"
> > +	  "in your initrd/initramfs image.\n");
> > +}
> > +
> >  static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
> >  {
> >  	struct drm_device *dev = dev_priv->dev;
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 47be4a5..90e47a9 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -667,6 +667,15 @@ struct intel_uncore {
> >  #define for_each_fw_domain(domain__, dev_priv__, i__) \
> >  	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
> >  
> > +struct intel_csr {
> > +	const char *fw_path;
> > +	__be32 *dmc_payload;
> > +	uint32_t dmc_fw_size;
> > +	uint32_t mmio_count;
> > +	uint32_t mmioaddr[8];
> > +	uint32_t mmiodata[8];
> > +};
> > +
> >  #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
> >  	func(is_mobile) sep \
> >  	func(is_i85x) sep \
> > @@ -1573,6 +1582,11 @@ struct drm_i915_private {
> >  
> >  	struct i915_virtual_gpu vgpu;
> >  
> > +	struct intel_csr csr;
> > +
> > +	/* Display CSR-related protection */
> > +	struct mutex csr_lock;
> > +
> >  	struct intel_gmbus gmbus[GMBUS_NUM_PINS];
> >  
> >  	/** gmbus_mutex protects against concurrent usage of the single hw gmbus
> > @@ -2425,6 +2439,8 @@ struct drm_i915_cmd_table {
> >  #define HAS_RC6(dev)		(INTEL_INFO(dev)->gen >= 6)
> >  #define HAS_RC6p(dev)		(INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
> >  
> > +#define HAS_CSR(dev)	(IS_SKYLAKE(dev))
> > +
> >  #define INTEL_PCH_DEVICE_ID_MASK		0xff00
> >  #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
> >  #define INTEL_PCH_CPT_DEVICE_ID_TYPE		0x1c00
> > @@ -2515,6 +2531,7 @@ extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
> >  extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
> >  int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
> >  void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
> > +void i915_firmware_load_error_print(const char *fw_path, int err);
> >  
> >  /* i915_irq.c */
> >  void i915_queue_hangcheck(struct drm_device *dev);
> > diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
> > new file mode 100644
> > index 0000000..f5fa574
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/intel_csr.c
> > @@ -0,0 +1,367 @@
> > +/*
> > + * Copyright © 2014 Intel Corporation
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a
> > + * copy of this software and associated documentation files (the "Software"),
> > + * to deal in the Software without restriction, including without limitation
> > + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> > + * and/or sell copies of the Software, and to permit persons to whom the
> > + * Software is furnished to do so, subject to the following conditions:
> > + *
> > + * The above copyright notice and this permission notice (including the next
> > + * paragraph) shall be included in all copies or substantial portions of the
> > + * Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> > + * IN THE SOFTWARE.
> > + *
> > + */
> > +#include <linux/firmware.h>
> > +#include "i915_drv.h"
> > +#include "i915_reg.h"
> > +
> > +#define I915_CSR_SKL "i915/skl_dmc_ver4.bin"
> > +
> > +MODULE_FIRMWARE(I915_CSR_SKL);
> > +
> > +/*
> > +* SKL CSR registers for DC5 and DC6
> > +*/
> > +#define CSR_PROGRAM_BASE		0x80000
> > +#define CSR_SSP_BASE_ADDR_GEN9		0x00002FC0
> > +#define CSR_HTP_ADDR_SKL		0x00500034
> > +#define CSR_SSP_BASE			0x8F074
> > +#define CSR_HTP_SKL			0x8F004
> > +#define CSR_LAST_WRITE			0x8F034
> > +#define CSR_LAST_WRITE_VALUE		0xc003b400
> > +/* MMIO address range for CSR program (0x80000 - 0x82FFF) */
> > +#define CSR_MAX_FW_SIZE			0x2FFF
> > +#define CSR_DEFAULT_FW_OFFSET		0xFFFFFFFF
> > +#define CSR_MMIO_START_RANGE	0x80000
> > +#define CSR_MMIO_END_RANGE		0x8FFFF
> > +
> > +struct intel_css_header {
> > +	/* 0x09 for DMC */
> > +	uint32_t module_type;
> > +
> > +	/* Includes the DMC specific header in dwords */
> > +	uint32_t header_len;
> > +
> > +	/* always value would be 0x10000 */
> > +	uint32_t header_ver;
> > +
> > +	/* Not used */
> > +	uint32_t module_id;
> > +
> > +	/* Not used */
> > +	uint32_t module_vendor;
> > +
> > +	/* in YYYYMMDD format */
> > +	uint32_t date;
> > +
> > +	/* Size in dwords (CSS_Headerlen + PackageHeaderLen + dmc FWsLen)/4 */
> > +	uint32_t size;
> > +
> > +	/* Not used */
> > +	uint32_t key_size;
> > +
> > +	/* Not used */
> > +	uint32_t modulus_size;
> > +
> > +	/* Not used */
> > +	uint32_t exponent_size;
> > +
> > +	/* Not used */
> > +	uint32_t reserved1[12];
> > +
> > +	/* Major Minor */
> > +	uint32_t version;
> > +
> > +	/* Not used */
> > +	uint32_t reserved2[8];
> > +
> > +	/* Not used */
> > +	uint32_t kernel_header_info;
> > +} __packed;
> > +
> > +struct intel_fw_info {
> > +	uint16_t reserved1;
> > +
> > +	/* Stepping (A, B, C, ..., *). * is a wildcard */
> > +	char stepping;
> > +
> > +	/* Sub-stepping (0, 1, ..., *). * is a wildcard */
> > +	char substepping;
> > +
> > +	uint32_t offset;
> > +	uint32_t reserved2;
> > +} __packed;
> > +
> > +struct intel_package_header {
> > +	/* DMC container header length in dwords */
> > +	unsigned char header_len;
> > +
> > +	/* always value would be 0x01 */
> > +	unsigned char header_ver;
> > +
> > +	unsigned char reserved[10];
> > +
> > +	/* Number of valid entries in the FWInfo array below */
> > +	uint32_t num_entries;
> > +
> > +	struct intel_fw_info fw_info[20];
> > +} __packed;
> > +
> > +struct intel_dmc_header {
> > +	/* always value would be 0x40403E3E */
> > +	uint32_t signature;
> > +
> > +	/* DMC binary header length */
> > +	unsigned char header_len;
> > +
> > +	/* 0x01 */
> > +	unsigned char header_ver;
> > +
> > +	/* Reserved */
> > +	uint16_t dmcc_ver;
> > +
> > +	/* Major, Minor */
> > +	uint32_t	project;
> > +
> > +	/* Firmware program size (excluding header) in dwords */
> > +	uint32_t	fw_size;
> > +
> > +	/* Major Minor version */
> > +	uint32_t fw_version;
> > +
> > +	/* Number of valid MMIO cycles present. */
> > +	uint32_t mmio_count;
> > +
> > +	/* MMIO address */
> > +	uint32_t mmioaddr[8];
> > +
> > +	/* MMIO data */
> > +	uint32_t mmiodata[8];
> > +
> > +	/* FW filename  */
> > +	unsigned char dfile[32];
> > +
> > +	uint32_t reserved1[2];
> > +} __packed;
> > +
> > +struct stepping_info {
> > +	char stepping;
> > +	char substepping;
> > +};
> > +
> > +static const struct stepping_info skl_stepping_info[] = {
> > +		{'A', '0'}, {'B', '0'}, {'C', '0'},
> > +		{'D', '0'}, {'E', '0'}, {'F', '0'},
> > +		{'G', '0'}, {'H', '0'}, {'I', '0'}
> > +};
> > +
> > +static char intel_get_stepping(struct drm_device *dev)
> > +{
> > +	if (IS_SKYLAKE(dev) && (dev->pdev->revision <
> > +			ARRAY_SIZE(skl_stepping_info)))
> > +		return skl_stepping_info[dev->pdev->revision].stepping;
> > +	else
> > +		return -ENODATA;
> > +}
> > +
> > +static char intel_get_substepping(struct drm_device *dev)
> > +{
> > +	if (IS_SKYLAKE(dev) && (dev->pdev->revision <
> > +			ARRAY_SIZE(skl_stepping_info)))
> > +		return skl_stepping_info[dev->pdev->revision].substepping;
> > +	else
> > +		return -ENODATA;
> > +}
> > +
> > +void intel_csr_load_program(struct drm_device *dev)
> > +{
> > +	struct drm_i915_private *dev_priv = dev->dev_private;
> > +	__be32 *payload = dev_priv->csr.dmc_payload;
> > +	uint32_t i, fw_size;
> > +
> > +	if (!IS_GEN9(dev)) {
> > +		DRM_ERROR("No CSR support available for this platform\n");
> > +		return;
> > +	}
> > +
> > +	mutex_lock(&dev_priv->csr_lock);
> > +	fw_size = dev_priv->csr.dmc_fw_size;
> > +	for (i = 0; i < fw_size; i++)
> > +		I915_WRITE(CSR_PROGRAM_BASE + i * 4,
> > +			(u32 __force)payload[i]);
> > +
> > +	for (i = 0; i < dev_priv->csr.mmio_count; i++) {
> > +		I915_WRITE(dev_priv->csr.mmioaddr[i],
> > +			dev_priv->csr.mmiodata[i]);
> > +	}
> > +	mutex_unlock(&dev_priv->csr_lock);
> > +}
> > +
> > +static void finish_csr_load(const struct firmware *fw, void *context)
> > +{
> > +	struct drm_i915_private *dev_priv = context;
> > +	struct drm_device *dev = dev_priv->dev;
> > +	struct intel_css_header *css_header;
> > +	struct intel_package_header *package_header;
> > +	struct intel_dmc_header *dmc_header;
> > +	struct intel_csr *csr = &dev_priv->csr;
> > +	char stepping = intel_get_stepping(dev);
> > +	char substepping = intel_get_substepping(dev);
> > +	uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
> > +	uint32_t i;
> > +	__be32 *dmc_payload;
> > +
> > +	if (!fw) {
> > +		i915_firmware_load_error_print(csr->fw_path, 0);
> > +		goto out;
> > +	}
> > +
> > +	if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
> > +		DRM_ERROR("Unknown stepping info, firmware loading failed\n");
> > +		goto out;
> > +	}
> > +
> > +	/* Extract CSS Header information*/
> > +	css_header = (struct intel_css_header *)fw->data;
> > +	if (sizeof(struct intel_css_header) !=
> > +		(css_header->header_len * 4)) {
> > +		DRM_ERROR("Firmware has wrong CSS header length %u bytes\n",
> > +			(css_header->header_len * 4));
> > +		goto out;
> > +	}
> > +	readcount += sizeof(struct intel_css_header);
> > +
> > +	/* Extract Package Header information*/
> > +	package_header = (struct intel_package_header *)
> > +					&fw->data[readcount];
> > +	if (sizeof(struct intel_package_header) !=
> > +		(package_header->header_len * 4)) {
> > +		DRM_ERROR("Firmware has wrong package header length %u bytes\n",
> > +			(package_header->header_len * 4));
> > +		goto out;
> > +	}
> > +	readcount += sizeof(struct intel_package_header);
> > +
> > +	/* Search for dmc_offset to find firware binary. */
> > +	for (i = 0; i < package_header->num_entries; i++) {
> > +		if (package_header->fw_info[i].substepping == '*' &&
> > +			stepping == package_header->fw_info[i].stepping) {
> > +			dmc_offset = package_header->fw_info[i].offset;
> > +			break;
> > +		} else if (stepping == package_header->fw_info[i].stepping &&
> > +			substepping == package_header->fw_info[i].substepping) {
> > +			dmc_offset = package_header->fw_info[i].offset;
> > +			break;
> > +		} else if (package_header->fw_info[i].stepping == '*' &&
> > +			package_header->fw_info[i].substepping == '*')
> > +			dmc_offset = package_header->fw_info[i].offset;
> > +	}
> > +	if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
> > +		DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
> > +		goto out;
> > +	}
> > +	readcount += dmc_offset;
> > +
> > +	/* Extract dmc_header information. */
> > +	dmc_header = (struct intel_dmc_header *)&fw->data[readcount];
> > +	if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) {
> > +		DRM_ERROR("Firmware has wrong dmc header length %u bytes\n",
> > +				(dmc_header->header_len));
> > +		goto out;
> > +	}
> > +	readcount += sizeof(struct intel_dmc_header);
> > +
> > +	/* Cache the dmc header info. */
> > +	if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) {
> > +		DRM_ERROR("Firmware has wrong mmio count %u\n",
> > +						dmc_header->mmio_count);
> > +		goto out;
> > +	}
> > +	csr->mmio_count = dmc_header->mmio_count;
> > +	for (i = 0; i < dmc_header->mmio_count; i++) {
> > +		if (dmc_header->mmioaddr[i] < CSR_MMIO_START_RANGE &&
> > +			dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
> > +			DRM_ERROR(" Firmware has wrong mmio address 0x%x\n",
> > +						dmc_header->mmioaddr[i]);
> > +			goto out;
> > +		}
> > +		csr->mmioaddr[i] = dmc_header->mmioaddr[i];
> > +		csr->mmiodata[i] = dmc_header->mmiodata[i];
> > +	}
> > +
> > +	/* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
> > +	nbytes = dmc_header->fw_size * 4;
> > +	if (nbytes > CSR_MAX_FW_SIZE) {
> > +		DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes);
> > +		goto out;
> > +	}
> > +	csr->dmc_fw_size = dmc_header->fw_size;
> > +
> > +	csr->dmc_payload = kmalloc(nbytes, GFP_KERNEL);
> > +	if (!csr->dmc_payload) {
> > +		DRM_ERROR("Memory allocation failed for dmc payload\n");
> > +		goto out;
> > +	}
> > +
> > +	dmc_payload = csr->dmc_payload;
> > +	for (i = 0; i < dmc_header->fw_size; i++) {
> > +		uint32_t *tmp = (u32 *)&fw->data[readcount + i * 4];
> > +		/*
> > +		 * The firmware payload is an array of 32 bit words stored in
> > +		 * little-endian format in the firmware image and programmed
> > +		 * as 32 bit big-endian format to memory.
> > +		 */
> > +		dmc_payload[i] = cpu_to_be32(*tmp);
> > +	}
> > +
> > +	/* load csr program during system boot, as needed for DC states */
> > +	intel_csr_load_program(dev);
> > +out:
> > +	release_firmware(fw);
> > +}
> > +
> > +void intel_csr_ucode_init(struct drm_device *dev)
> > +{
> > +	struct drm_i915_private *dev_priv = dev->dev_private;
> > +	struct intel_csr *csr = &dev_priv->csr;
> > +	int ret;
> > +
> > +	if (!HAS_CSR(dev))
> > +		return;
> > +
> > +	if (IS_SKYLAKE(dev))
> > +		csr->fw_path = I915_CSR_SKL;
> > +	else {
> > +		DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
> > +		return;
> > +	}
> > +
> > +	/* CSR supported for platform, load firmware */
> > +	ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path,
> > +				&dev_priv->dev->pdev->dev,
> > +				GFP_KERNEL, dev_priv,
> > +				finish_csr_load);
> > +	if (ret)
> > +		i915_firmware_load_error_print(csr->fw_path, ret);
> > +
> > +}
> > +
> > +void intel_csr_ucode_fini(struct drm_device *dev)
> > +{
> > +	struct drm_i915_private *dev_priv = dev->dev_private;
> > +
> > +	if (!HAS_CSR(dev))
> > +		return;
> > +
> > +	kfree(dev_priv->csr.dmc_payload);
> > +}
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 7a0aa24..f3a2d88 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1062,6 +1062,11 @@ void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
> >  unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
> >  				     struct drm_i915_gem_object *obj);
> >  
> > +/* intel_csr.c */
> > +void intel_csr_ucode_init(struct drm_device *dev);
> > +void intel_csr_load_program(struct drm_device *dev);
> > +void intel_csr_ucode_fini(struct drm_device *dev);
> > +
> >  /* intel_dp.c */
> >  void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
> >  bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
> 
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
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] 37+ messages in thread

* Re: [PATCH v5 2/2] drm/i915/skl: Add DC5 Trigger Sequence
  2015-04-17 14:16           ` [PATCH v5 2/2] " Animesh Manna
  2015-04-30 13:18             ` Imre Deak
@ 2015-05-04  9:39             ` Daniel Vetter
  1 sibling, 0 replies; 37+ messages in thread
From: Daniel Vetter @ 2015-05-04  9:39 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On Fri, Apr 17, 2015 at 07:46:16PM +0530, Animesh Manna wrote:
> From: Suketu Shah <suketu.j.shah@intel.com>
> 
> Add triggers as per expectations mentioned in gen9_enable_dc5
> and gen9_disable_dc5 patch.
> 
> Also call POSTING_READ for every write to a register to ensure that
> its written immediately.
> 
> v1: Remove POSTING_READ calls as they've already been added in previous patches.
> 
> v2: Rebase to move all runtime pm specific changes to intel_runtime_pm.c file.
> 
> Modified as per review comments from Imre:
> 1] Change variable name 'dc5_allowed' to 'dc5_enabled' to correspond to relevant
>    functions.
> 2] Move the check dc5_enabled in skl_set_power_well() to disable DC5 into
>    gen9_disable_DC5 which is a more appropriate place.
> 3] Convert checks for 'pm.dc5_enabled' and 'pm.suspended' in skl_set_power_well()
>    to warnings. However, removing them for now as they'll be included in a future patch
>    asserting DC-state entry/exit criteria.
> 4] Enable DC5, only when CSR firmware is verified to be loaded. Create new structure
>    to track 'enabled' and 'deferred' status of DC5.
> 5] Ensure runtime PM reference is obtained, if CSR is not loaded, to avoid entering
>    runtime-suspend and release it when it's loaded.
> 6] Protect necessary CSR-related code with locks.
> 7] Move CSR-loading call to runtime PM initialization, as power domains needed to be
>    accessed during deferred DC5-enabling, are not initialized earlier.
> 
> v3: Rebase to latest.
> 
> Modified as per review comments from Imre:
> 1] Use blocking wait for CSR-loading to finish to enable DC5  for simplicity, instead of
>    deferring enabling DC5 until CSR is loaded.
> 2] Obtain runtime PM reference during CSR-loading initialization itself as deferred DC5-
>    enabling is removed and release it at the end of CSR-loading functionality.
> 3] Revert calling CSR-loading functionality to the beginning of i915 driver-load
>    functionality to avoid any delay in loading.
> 4] Define another variable to track whether CSR-loading failed and use it to avoid enabling
>    DC5 if it's true.
> 5] Define CSR-load-status accessor functions for use later.
> 
> v4:
> 1] Disable DC5 before enabling PG2 instead of after it.
> 2] DC5 was being mistaken enabled even when CSR-loading timed-out. Fix that.
> 3] Enable DC5-related functionality using a macro.
> 4] Remove dc5_enabled tracking variable and its use as it's not needed now.
> 
> v5:
> 1] Mark CSR failed to load where necessary in finish_csr_load function.
> 2] Use mutex-protected accessor function to check if CSR loaded instead of directly
>    accessing the variable.
> 3] Prefix csr_load_status_get/set function names with intel_.
> 
> v6: rebase to latest.
> v7: Rebase on top of nightly (Damien)
> v8: Squashed the patch from Imre - added csr helper pointers to simplify the code. (Imre)
> v9: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)
> v10: Added a enum for different csr states, suggested by Imre. (Animesh)
> 
> v11: Based on review comments from Imre, Damien and Daniel following changes done
> - enum name chnaged to csr_state (singular form).
> - FW_UNINITIALIZED used as zeroth element in enum csr_state.
> - Prototype changed for helper function(set/get csr status), using enum csr_state instead of bool.
> 
> v12: Based on review comment from Imre, introduced bool fw_loaded local to finish_csr_load() which helps
> calling once to set the csr status. The same flag used to fail RPM if find any issue during
> firmware loading.
> 
> Issue: VIZ-2819
> Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com>
> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h         |  7 ++++++
>  drivers/gpu/drm/i915/intel_csr.c        | 42 +++++++++++++++++++++++++++++++--
>  drivers/gpu/drm/i915/intel_drv.h        |  3 +++
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 33 ++++++++++++++++++++++++++
>  4 files changed, 83 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 90e47a9..670e407 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -667,6 +667,12 @@ struct intel_uncore {
>  #define for_each_fw_domain(domain__, dev_priv__, i__) \
>  	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
>  
> +enum csr_state {
> +	FW_UNINITIALIZED = 0,
> +	FW_LOADED,
> +	FW_FAILED
> +};
> +
>  struct intel_csr {
>  	const char *fw_path;
>  	__be32 *dmc_payload;
> @@ -674,6 +680,7 @@ struct intel_csr {
>  	uint32_t mmio_count;
>  	uint32_t mmioaddr[8];
>  	uint32_t mmiodata[8];
> +	enum csr_state state;
>  };
>  
>  #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
> diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
> index f5fa574..3bd29b5 100644
> --- a/drivers/gpu/drm/i915/intel_csr.c
> +++ b/drivers/gpu/drm/i915/intel_csr.c
> @@ -183,6 +183,25 @@ static char intel_get_substepping(struct drm_device *dev)
>  		return -ENODATA;
>  }
>  
> +enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv)
> +{
> +	enum csr_state state;
> +
> +	mutex_lock(&dev_priv->csr_lock);
> +	state = dev_priv->csr.state;
> +	mutex_unlock(&dev_priv->csr_lock);
> +
> +	return state;
> +}
> +
> +void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
> +			enum csr_state state)
> +{
> +	mutex_lock(&dev_priv->csr_lock);
> +	dev_priv->csr.state = state;
> +	mutex_unlock(&dev_priv->csr_lock);
> +}
> +
>  void intel_csr_load_program(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -204,6 +223,8 @@ void intel_csr_load_program(struct drm_device *dev)
>  		I915_WRITE(dev_priv->csr.mmioaddr[i],
>  			dev_priv->csr.mmiodata[i]);
>  	}
> +
> +	dev_priv->csr.state = FW_LOADED;
>  	mutex_unlock(&dev_priv->csr_lock);
>  }
>  
> @@ -220,6 +241,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  	uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
>  	uint32_t i;
>  	__be32 *dmc_payload;
> +	bool fw_loaded = false;
>  
>  	if (!fw) {
>  		i915_firmware_load_error_print(csr->fw_path, 0);
> @@ -326,7 +348,14 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  
>  	/* load csr program during system boot, as needed for DC states */
>  	intel_csr_load_program(dev);
> +	fw_loaded = true;
> +
>  out:
> +	if (fw_loaded)
> +		intel_runtime_pm_put(dev_priv);
> +	else
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> +
>  	release_firmware(fw);
>  }
>  
> @@ -343,17 +372,25 @@ void intel_csr_ucode_init(struct drm_device *dev)
>  		csr->fw_path = I915_CSR_SKL;
>  	else {
>  		DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
>  		return;
>  	}
>  
> +	/*
> +	 * Obtain a runtime pm reference, until CSR is loaded,
> +	 * to avoid entering runtime-suspend.
> +	 */
> +	intel_runtime_pm_get(dev_priv);
> +
>  	/* CSR supported for platform, load firmware */
>  	ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path,
>  				&dev_priv->dev->pdev->dev,
>  				GFP_KERNEL, dev_priv,
>  				finish_csr_load);
> -	if (ret)
> +	if (ret) {
>  		i915_firmware_load_error_print(csr->fw_path, ret);
> -
> +		intel_csr_load_status_set(dev_priv, FW_FAILED);
> +	}
>  }
>  
>  void intel_csr_ucode_fini(struct drm_device *dev)
> @@ -363,5 +400,6 @@ void intel_csr_ucode_fini(struct drm_device *dev)
>  	if (!HAS_CSR(dev))
>  		return;
>  
> +	intel_csr_load_status_set(dev_priv, FW_FAILED);
>  	kfree(dev_priv->csr.dmc_payload);
>  }
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index f3a2d88..25d7956 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1064,6 +1064,9 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
>  
>  /* intel_csr.c */
>  void intel_csr_ucode_init(struct drm_device *dev);
> +enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv);
> +void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
> +					enum csr_state state);
>  void intel_csr_load_program(struct drm_device *dev);
>  void intel_csr_ucode_fini(struct drm_device *dev);
>  
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index ce00e69..23f02a8 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -49,6 +49,8 @@
>   * present for a given platform.
>   */
>  
> +#define GEN9_ENABLE_DC5(dev) (IS_SKYLAKE(dev))
> +
>  #define for_each_power_well(i, power_well, domain_mask, power_domains)	\
>  	for (i = 0;							\
>  	     i < (power_domains)->power_well_count &&			\
> @@ -319,9 +321,20 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
>  	SKL_DISPLAY_MISC_IO_POWER_DOMAINS)) |		\
>  	BIT(POWER_DOMAIN_INIT))
>  
> +static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
> +{
> +	/* TODO: Implementation to be done. */
> +}
> +
> +static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
> +{
> +	/* TODO: Implementation to be done. */
> +}
> +
>  static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  			struct i915_power_well *power_well, bool enable)
>  {
> +	struct drm_device *dev = dev_priv->dev;
>  	uint32_t tmp, fuse_status;
>  	uint32_t req_mask, state_mask;
>  	bool is_enabled, enable_requested, check_fuse_status = false;
> @@ -361,6 +374,13 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  
>  	if (enable) {
>  		if (!enable_requested) {
> +			WARN((tmp & state_mask) &&
> +				!I915_READ(HSW_PWR_WELL_BIOS),
> +				"Invalid for power well status to be enabled, unless done by the BIOS, \
> +				when request is to disable!\n");
> +			if (GEN9_ENABLE_DC5(dev) &&
> +				power_well->data == SKL_DISP_PW_2)
> +				gen9_disable_dc5(dev_priv);
>  			I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask);
>  		}
>  
> @@ -377,6 +397,19 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  			I915_WRITE(HSW_PWR_WELL_DRIVER,	tmp & ~req_mask);
>  			POSTING_READ(HSW_PWR_WELL_DRIVER);
>  			DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
> +
> +			if (GEN9_ENABLE_DC5(dev) &&
> +				power_well->data == SKL_DISP_PW_2) {
> +				enum csr_state state;
> +
> +				wait_for((state = intel_csr_load_status_get(dev_priv)) !=
> +						FW_UNINITIALIZED, 1000);
> +				if (state != FW_LOADED)
> +					DRM_ERROR("CSR firmware not ready (%d)\n",
> +							state);
> +				else
> +					gen9_enable_dc5(dev_priv);

Imo indentation levels are excessive here, can you please throw a refactor
patch on top to extract this into a small helper?
-Daniel

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

-- 
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] 37+ messages in thread

* Re: [PATCH v4 5/8] drm/i915/skl: Add DC6 Trigger sequence.
  2015-04-16  8:52 ` [PATCH v4 5/8] drm/i915/skl: Add DC6 Trigger sequence Animesh Manna
  2015-04-30 13:41   ` Imre Deak
@ 2015-05-04  9:44   ` Daniel Vetter
  2015-05-04 13:05   ` Daniel Vetter
  2 siblings, 0 replies; 37+ messages in thread
From: Daniel Vetter @ 2015-05-04  9:44 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On Thu, Apr 16, 2015 at 02:22:11PM +0530, Animesh Manna wrote:
> From: Suketu Shah <suketu.j.shah@intel.com>
> 
> Add triggers for DC6 as per details provided in skl_enable_dc6
> and skl_disable_dc6 implementations.
> 
> Also Call POSTING_READ for every write to a register to ensure
> it is written to immediately
> 
> v1: Remove POSTING_READ and intel_prepare_ddi calls as they've been added in previous patches.
> 
> v2:
> 1] Remove check for backlight disabled as it should be the case by that time.
> 2] Mark DC5 as disabled when enabling DC6.
> 3] Return from DC5-disabling function early if DC5 is already be disabled which can happen
>    due to DC6-enabling earlier.
> 3] Ensure CSR firmware is loaded after resume from DC6 as corresponding memory contents won't
>    be retained after runtime-suspend.
> 4] Ensure that CSR isn't identified as loaded before CSR-loading program is called during
>    runtime-resume.
> 
> v3: Rebase to latest
> Modified as per review comments from Imre and after discussion with Art:
> 1] DC6 should be preferably enabled when PG2 is disabled by SW as the check for PG1 being
>    disabled is taken of by HW to enter DC6, and disabled when PG2 is enabled respectively.
>    This helps save more power, especially in the case when display is disabled but GT is
>    enabled. Accordingly, replacing DC5 trigger sequence with DC6 for SKL.
> 2] DC6 could be enabled from intel_runtime_suspend() function, if DC5 is already enabled.
> 3] Move CSR-load-status setting code from intel_runtime_suspend function to a new function.
> 
> v4:
> 1] Enable/disable DC6 only when toggling the power-well using a newly defined macro ENABLE_DC6.
> 
> v5:
> 1] Load CSR on system resume too as firmware may be lost on system suspend preventing
>    enabling DC5, DC6.
> 2] DDI buffers shouldn't be programmed during driver-load/resume as it's already done
>    during modeset initialization then and also that the encoder list is still uninitialized by
>    then. Therefore, call intel_prepare_ddi function right after disabling DC6 but outside
>    skl_disable_dc6 function and not during driver-load/resume.
> 
> v6:
> 1] Rebase to latest.
> 2] Move SKL_ENABLE_DC6 macro definition from intel_display.c to intel_runtime_pm.c.
> 
> v7:
> 1) Refactored the code for removing the warning got from checkpatch.
> 2) After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)
> 
> v8:
> - Reverted the changes done in v7.
> - Removed the condition check in skl_prepare_resune(). (Animesh)
> 
> Issue: VIZ-2819
> Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com>
> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c         | 30 +++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 43 +++++++++++++++++++++++++++------
>  2 files changed, 66 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index acd0e2b..0f590e3 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -594,6 +594,8 @@ static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
>  static int intel_suspend_complete(struct drm_i915_private *dev_priv);
>  static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
>  			      bool rpm_resume);
> +static int skl_resume_prepare(struct drm_i915_private *dev_priv);
> +
>  
>  static int i915_drm_suspend(struct drm_device *dev)
>  {
> @@ -808,6 +810,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
>  
>  	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
>  		hsw_disable_pc8(dev_priv);
> +	else if (IS_SKYLAKE(dev_priv))
> +		ret = skl_resume_prepare(dev_priv);
>  
>  	intel_uncore_sanitize(dev);
>  	intel_power_domains_init_hw(dev_priv);
> @@ -1022,6 +1026,19 @@ static int i915_pm_resume(struct device *dev)
>  	return i915_drm_resume(drm_dev);
>  }
>  
> +static int skl_suspend_complete(struct drm_i915_private *dev_priv)
> +{
> +	/* Enabling DC6 is not a hard requirement to enter runtime D3 */
> +
> +	/*
> +	 * This is to ensure that CSR isn't identified as loaded before
> +	 * CSR-loading program is called during runtime-resume.
> +	 */
> +	intel_csr_load_status_set(dev_priv, FW_UNINITIALIZED);
> +
> +	return 0;
> +}
> +
>  static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
>  {
>  	hsw_enable_pc8(dev_priv);
> @@ -1029,6 +1046,15 @@ static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
>  	return 0;
>  }
>  
> +static int skl_resume_prepare(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +
> +	intel_csr_load_program(dev);
> +
> +	return 0;
> +}
> +
>  /*
>   * Save all Gunit registers that may be lost after a D3 and a subsequent
>   * S0i[R123] transition. The list of registers needing a save/restore is
> @@ -1487,6 +1513,8 @@ static int intel_runtime_resume(struct device *device)
>  
>  	if (IS_GEN6(dev_priv))
>  		intel_init_pch_refclk(dev);
> +	else if (IS_SKYLAKE(dev))
> +		ret = skl_resume_prepare(dev_priv);

I resolved the conflicts with bxt support here assuming that there's no
functional conflicts since dc6 is skl-only. But please double-check just
to make sure.

>  	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
>  		hsw_disable_pc8(dev_priv);
>  	else if (IS_VALLEYVIEW(dev_priv))
> @@ -1519,6 +1547,8 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv)
>  	struct drm_device *dev = dev_priv->dev;
>  	int ret;
>  
> +	if (IS_SKYLAKE(dev))
> +		ret = skl_suspend_complete(dev_priv);
>  	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
>  		ret = hsw_suspend_complete(dev_priv);
>  	else if (IS_VALLEYVIEW(dev))
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index da8c18d..7e6908e 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -49,7 +49,8 @@
>   * present for a given platform.
>   */
>  
> -#define GEN9_ENABLE_DC5(dev) (IS_SKYLAKE(dev))
> +#define GEN9_ENABLE_DC5(dev) 0
> +#define SKL_ENABLE_DC6(dev) IS_SKYLAKE(dev)
>  
>  #define for_each_power_well(i, power_well, domain_mask, power_domains)	\
>  	for (i = 0;							\
> @@ -397,6 +398,16 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
>  	POSTING_READ(DC_STATE_EN);
>  }
>  
> +static void skl_enable_dc6(struct drm_i915_private *dev_priv)
> +{
> +	/* TODO: Implementation to be done. */
> +}
> +
> +static void skl_disable_dc6(struct drm_i915_private *dev_priv)
> +{
> +	/* TODO: Implementation to be done. */
> +}
> +
>  static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  			struct i915_power_well *power_well, bool enable)
>  {
> @@ -444,9 +455,21 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  				!I915_READ(HSW_PWR_WELL_BIOS),
>  				"Invalid for power well status to be enabled, unless done by the BIOS, \
>  				when request is to disable!\n");
> -			if (GEN9_ENABLE_DC5(dev) &&
> -				power_well->data == SKL_DISP_PW_2)
> -				gen9_disable_dc5(dev_priv);
> +			if ((GEN9_ENABLE_DC5(dev) || SKL_ENABLE_DC6(dev)) &&
> +				power_well->data == SKL_DISP_PW_2) {
> +				if (SKL_ENABLE_DC6(dev)) {
> +					skl_disable_dc6(dev_priv);
> +					/*
> +					 * DDI buffer programming unnecessary during driver-load/resume
> +					 * as it's already done during modeset initialization then.
> +					 * It's also invalid here as encoder list is still uninitialized.
> +					 */
> +					if (!dev_priv->power_domains.initializing)
> +						intel_prepare_ddi(dev);
> +				} else {
> +					gen9_disable_dc5(dev_priv);
> +				}
> +			}
>  			I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask);
>  		}
>  
> @@ -464,17 +487,23 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  			POSTING_READ(HSW_PWR_WELL_DRIVER);
>  			DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
>  
> -			if (GEN9_ENABLE_DC5(dev) &&
> +			if ((GEN9_ENABLE_DC5(dev) || SKL_ENABLE_DC6(dev)) &&
>  				power_well->data == SKL_DISP_PW_2) {
>  				enum csr_state state;
> -
> +				/* TODO: wait for a completion event or
> +				 * similar here instead of busy
> +				 * waiting using wait_for function.
> +				 */
>  				wait_for((state = intel_csr_load_status_get(dev_priv)) !=
>  						FW_UNINITIALIZED, 1000);
>  				if (state != FW_LOADED)
>  					DRM_ERROR("CSR firmware not ready (%d)\n",
>  							state);
>  				else
> -					gen9_enable_dc5(dev_priv);
> +					if (SKL_ENABLE_DC6(dev))
> +						skl_enable_dc6(dev_priv);
> +					else
> +						gen9_enable_dc5(dev_priv);

Yep, skl_set_power_well is definitely going over the top. Rule of thumb is
that you shouldn't use more than 3 tabs in a function, maybe 4 for an if
(error_condition) baile_out; check.
-Daniel

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

-- 
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] 37+ messages in thread

* Re: [PATCH v5 1/8] drm/i915/skl: Add support to load SKL CSR firmware.
  2015-05-04  9:30         ` Daniel Vetter
@ 2015-05-04 10:31           ` Imre Deak
  0 siblings, 0 replies; 37+ messages in thread
From: Imre Deak @ 2015-05-04 10:31 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On ma, 2015-05-04 at 11:30 +0200, Daniel Vetter wrote:
> On Thu, Apr 30, 2015 at 04:02:34PM +0300, Imre Deak wrote:
> > On ke, 2015-04-29 at 22:59 +0530, Animesh Manna wrote:
> > > From: "A.Sunil Kamath" <sunil.kamath@intel.com>
> > > 
> > > Display Context Save and Restore support is needed for
> > > various SKL Display C states like DC5, DC6.
> > > 
> > > This implementation is added based on first version of DMC CSR program
> > > that we received from h/w team.
> > > 
> > > Here we are using request_firmware based design.
> > > Finally this firmware should end up in linux-firmware tree.
> > > 
> > > For SKL platform its mandatory to ensure that we load this
> > > csr program before enabling DC states like DC5/DC6.
> > > 
> > > As CSR program gets reset on various conditions, we should ensure
> > > to load it during boot and in future change to be added to load
> > > this system resume sequence too.
> > > 
> > > v1: Initial relese as RFC patch
> > > 
> > > v2: Design change as per Daniel, Damien and Shobit's review comments
> > > request firmware method followed.
> > > 
> > > v3: Some optimization and functional changes.
> > > Pulled register defines into drivers/gpu/drm/i915/i915_reg.h
> > > Used kmemdup to allocate and duplicate firmware content.
> > > Ensured to free allocated buffer.
> > > 
> > > v4: Modified as per review comments from Satheesh and Daniel
> > > Removed temporary buffer.
> > > Optimized number of writes by replacing I915_WRITE with I915_WRITE64.
> > > 
> > > v5:
> > > Modified as per review comemnts from Damien.
> > > - Changed name for functions and firmware.
> > > - Introduced HAS_CSR.
> > > - Reverted back previous change and used csr_buf with u8 size.
> > > - Using cpu_to_be64 for endianness change.
> > > 
> > > Modified as per review comments from Imre.
> > > - Modified registers and macro names to be a bit closer to bspec terminology
> > > and the existing register naming in the driver.
> > > - Early return for non SKL platforms in intel_load_csr_program function.
> > > - Added locking around CSR program load function as it may be called
> > > concurrently during system/runtime resume.
> > > - Releasing the fw before loading the program for consistency
> > > - Handled error path during f/w load.
> > > 
> > > v6: Modified as per review comments from Imre.
> > > - Corrected out_freecsr sequence.
> > > 
> > > v7: Modified as per review comments from Imre.
> > > Fail loading fw if fw->size%8!=0.
> > > 
> > > v8: Rebase to latest.
> > > 
> > > v9: Rebase on top of -nightly (Damien)
> > > 
> > > v10: Enabled support for dmc firmware ver 1.0.
> > > According to ver 1.0 in a single binary package all the firmware's that are
> > > required for different stepping's of the product will be stored. The package
> > > contains the css header, followed by the package header and the actual dmc
> > > firmwares. Package header contains the firmware/stepping mapping table and
> > > the corresponding firmware offsets to the individual binaries, within the
> > > package. Each individual program binary contains the header and the payload
> > > sections whose size is specified in the header section. This changes are done
> > > to extract the specific firmaware from the package. (Animesh)
> > > 
> > > v11: Modified as per review comemnts from Imre.
> > > - Added code comment from bpec for header structure elements.
> > > - Added __packed to avoid structure padding.
> > > - Added helper functions for stepping and substepping info.
> > > - Added code comment for CSR_MAX_FW_SIZE.
> > > - Disabled BXT firmware loading, will be enabled with dmc 1.0 support.
> > > - Changed skl_stepping_info based on bspec, earlier used from config DB.
> > > - Removed duplicate call of cpu_to_be* from intel_csr_load_program function.
> > > - Used cpu_to_be32 instead of cpu_to_be64 as firmware binary in dword aligned.
> > > - Added sanity check for header length.
> > > - Added sanity check for mmio address got from firmware binary.
> > > - kmalloc done separately for dmc header and dmc firmware. (Animesh)
> > > 
> > > v12: Modified as per review comemnts from Imre.
> > > - Corrected the typo error in skl stepping info structure.
> > > - Added out-of-bound access for skl_stepping_info.
> > > - Sanity check for mmio address modified.
> > > - Sanity check added for stepping and substeppig.
> > > - Modified the intel_dmc_info structure, cache only the required header info. (Animesh)
> > > 
> > > v13: clarify firmware load error message.
> > > The reason for a firmware loading failure can be obscure if the driver
> > > is built-in. Provide an explanation to the user about the likely reason for
> > > the failure and how to resolve it. (Imre)
> > > 
> > > v14: Suggested by Jani.
> > > - fix s/I915/CONFIG_DRM_I915/ typo
> > > - add fw_path to the firmware object instead of using a static ptr (Jani)
> > > 
> > > v15:
> > > 1) Changed the firmware name as dmc_gen9.bin, everytime for a new firmware version a symbolic link
> > > with same name will help not to build kernel again.
> > > 2) Changes done as per review comments from Imre.
> > > - Error check removed for intel_csr_ucode_init.
> > > - Moved csr-specific data structure to intel_csr.h and optimization done on structure definition.
> > > - fw->data used directly for parsing the header info & memory allocation
> > > only done separately for payload. (Animesh)
> > > 
> > > v16:
> > > - No need for out_regs label in i915_driver_load(), so removed it.
> > > - Changed the firmware name as skl_dmc_ver1.bin, followed naming convention <platform>_dmc_<api-version>.bin (Animesh)
> > > 
> > > Issue: VIZ-2569
> > > Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
> > > Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> > > Signed-off-by: Animesh Manna <animesh.manna@intel.com>
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > 
> > For the future: scripts/checkpatch.pl has a valid warning about the
> > commit message, please fix the issues reported by this tool next time.
> 
> Hm, what does checkpatch complain about - mine didn't?
> I did apply the patch manually though.

Too long commit message lines. Though one of those was from me:/

--Imre


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

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

* Re: [PATCH v5 1/8] drm/i915/skl: Add support to load SKL CSR firmware.
  2015-04-29 17:29     ` [PATCH v5 " Animesh Manna
  2015-04-30 13:02       ` Imre Deak
@ 2015-05-04 12:54       ` Daniel Vetter
  1 sibling, 0 replies; 37+ messages in thread
From: Daniel Vetter @ 2015-05-04 12:54 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx

On Wed, Apr 29, 2015 at 10:59:20PM +0530, Animesh Manna wrote:
> From: "A.Sunil Kamath" <sunil.kamath@intel.com>
> 
> Display Context Save and Restore support is needed for
> various SKL Display C states like DC5, DC6.
> 
> This implementation is added based on first version of DMC CSR program
> that we received from h/w team.
> 
> Here we are using request_firmware based design.
> Finally this firmware should end up in linux-firmware tree.
> 
> For SKL platform its mandatory to ensure that we load this
> csr program before enabling DC states like DC5/DC6.
> 
> As CSR program gets reset on various conditions, we should ensure
> to load it during boot and in future change to be added to load
> this system resume sequence too.
> 
> v1: Initial relese as RFC patch
> 
> v2: Design change as per Daniel, Damien and Shobit's review comments
> request firmware method followed.
> 
> v3: Some optimization and functional changes.
> Pulled register defines into drivers/gpu/drm/i915/i915_reg.h
> Used kmemdup to allocate and duplicate firmware content.
> Ensured to free allocated buffer.
> 
> v4: Modified as per review comments from Satheesh and Daniel
> Removed temporary buffer.
> Optimized number of writes by replacing I915_WRITE with I915_WRITE64.
> 
> v5:
> Modified as per review comemnts from Damien.
> - Changed name for functions and firmware.
> - Introduced HAS_CSR.
> - Reverted back previous change and used csr_buf with u8 size.
> - Using cpu_to_be64 for endianness change.
> 
> Modified as per review comments from Imre.
> - Modified registers and macro names to be a bit closer to bspec terminology
> and the existing register naming in the driver.
> - Early return for non SKL platforms in intel_load_csr_program function.
> - Added locking around CSR program load function as it may be called
> concurrently during system/runtime resume.
> - Releasing the fw before loading the program for consistency
> - Handled error path during f/w load.
> 
> v6: Modified as per review comments from Imre.
> - Corrected out_freecsr sequence.
> 
> v7: Modified as per review comments from Imre.
> Fail loading fw if fw->size%8!=0.
> 
> v8: Rebase to latest.
> 
> v9: Rebase on top of -nightly (Damien)
> 
> v10: Enabled support for dmc firmware ver 1.0.
> According to ver 1.0 in a single binary package all the firmware's that are
> required for different stepping's of the product will be stored. The package
> contains the css header, followed by the package header and the actual dmc
> firmwares. Package header contains the firmware/stepping mapping table and
> the corresponding firmware offsets to the individual binaries, within the
> package. Each individual program binary contains the header and the payload
> sections whose size is specified in the header section. This changes are done
> to extract the specific firmaware from the package. (Animesh)
> 
> v11: Modified as per review comemnts from Imre.
> - Added code comment from bpec for header structure elements.
> - Added __packed to avoid structure padding.
> - Added helper functions for stepping and substepping info.
> - Added code comment for CSR_MAX_FW_SIZE.
> - Disabled BXT firmware loading, will be enabled with dmc 1.0 support.
> - Changed skl_stepping_info based on bspec, earlier used from config DB.
> - Removed duplicate call of cpu_to_be* from intel_csr_load_program function.
> - Used cpu_to_be32 instead of cpu_to_be64 as firmware binary in dword aligned.
> - Added sanity check for header length.
> - Added sanity check for mmio address got from firmware binary.
> - kmalloc done separately for dmc header and dmc firmware. (Animesh)
> 
> v12: Modified as per review comemnts from Imre.
> - Corrected the typo error in skl stepping info structure.
> - Added out-of-bound access for skl_stepping_info.
> - Sanity check for mmio address modified.
> - Sanity check added for stepping and substeppig.
> - Modified the intel_dmc_info structure, cache only the required header info. (Animesh)
> 
> v13: clarify firmware load error message.
> The reason for a firmware loading failure can be obscure if the driver
> is built-in. Provide an explanation to the user about the likely reason for
> the failure and how to resolve it. (Imre)
> 
> v14: Suggested by Jani.
> - fix s/I915/CONFIG_DRM_I915/ typo
> - add fw_path to the firmware object instead of using a static ptr (Jani)
> 
> v15:
> 1) Changed the firmware name as dmc_gen9.bin, everytime for a new firmware version a symbolic link
> with same name will help not to build kernel again.
> 2) Changes done as per review comments from Imre.
> - Error check removed for intel_csr_ucode_init.
> - Moved csr-specific data structure to intel_csr.h and optimization done on structure definition.
> - fw->data used directly for parsing the header info & memory allocation
> only done separately for payload. (Animesh)
> 
> v16:
> - No need for out_regs label in i915_driver_load(), so removed it.
> - Changed the firmware name as skl_dmc_ver1.bin, followed naming convention <platform>_dmc_<api-version>.bin (Animesh)
> 
> Issue: VIZ-2569
> Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile    |   3 +-
>  drivers/gpu/drm/i915/i915_dma.c  |  11 +-
>  drivers/gpu/drm/i915/i915_drv.c  |  20 +++
>  drivers/gpu/drm/i915/i915_drv.h  |  17 ++
>  drivers/gpu/drm/i915/intel_csr.c | 367 +++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h |   5 +
>  6 files changed, 420 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/intel_csr.c
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index a69002e..5238deb 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_csr.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 e44116f..a238889 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -816,6 +816,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  	spin_lock_init(&dev_priv->mmio_flip_lock);
>  	mutex_init(&dev_priv->dpio_lock);
>  	mutex_init(&dev_priv->modeset_restore_lock);
> +	mutex_init(&dev_priv->csr_lock);
>  
>  	intel_pm_setup(dev);
>  
> @@ -861,9 +862,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  
>  	intel_uncore_init(dev);
>  
> +	/* Load CSR Firmware for SKL */
> +	intel_csr_ucode_init(dev);
> +
>  	ret = i915_gem_gtt_init(dev);
>  	if (ret)
> -		goto out_regs;
> +		goto out_freecsr;
>  
>  	/* WARNING: Apparently we must kick fbdev drivers before vgacon,
>  	 * otherwise the vga fbdev driver falls over. */
> @@ -1033,7 +1037,8 @@ out_mtrrfree:
>  	io_mapping_free(dev_priv->gtt.mappable);
>  out_gtt:
>  	i915_global_gtt_cleanup(dev);
> -out_regs:
> +out_freecsr:
> +	intel_csr_ucode_fini(dev);
>  	intel_uncore_fini(dev);
>  	pci_iounmap(dev->pdev, dev_priv->regs);
>  put_bridge:
> @@ -1113,6 +1118,8 @@ int i915_driver_unload(struct drm_device *dev)
>  	mutex_unlock(&dev->struct_mutex);
>  	i915_gem_cleanup_stolen(dev);
>  
> +	intel_csr_ucode_fini(dev);
> +
>  	intel_teardown_gmbus(dev);
>  	intel_teardown_mchbar(dev);
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index c3fdbb0..acd0e2b 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -556,6 +556,26 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
>  	cancel_delayed_work_sync(&dev_priv->hotplug_reenable_work);
>  }
>  
> +void i915_firmware_load_error_print(const char *fw_path, int err)
> +{
> +	DRM_ERROR("failed to load firmware %s (%d)\n", fw_path, err);
> +
> +	/*
> +	 * If the reason is not known assume -ENOENT since that's the most
> +	 * usual failure mode.
> +	 */
> +	if (!err)
> +		err = -ENOENT;
> +
> +	if (!(IS_BUILTIN(CONFIG_DRM_I915) && err == -ENOENT))
> +		return;
> +
> +	DRM_ERROR(
> +	  "The driver is built-in, so to load the firmware you need to\n"
> +	  "include it either in the kernel (see CONFIG_EXTRA_FIRMWARE) or\n"
> +	  "in your initrd/initramfs image.\n");
> +}
> +
>  static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
>  {
>  	struct drm_device *dev = dev_priv->dev;
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 47be4a5..90e47a9 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -667,6 +667,15 @@ struct intel_uncore {
>  #define for_each_fw_domain(domain__, dev_priv__, i__) \
>  	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
>  
> +struct intel_csr {
> +	const char *fw_path;
> +	__be32 *dmc_payload;
> +	uint32_t dmc_fw_size;
> +	uint32_t mmio_count;
> +	uint32_t mmioaddr[8];
> +	uint32_t mmiodata[8];
> +};
> +
>  #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
>  	func(is_mobile) sep \
>  	func(is_i85x) sep \
> @@ -1573,6 +1582,11 @@ struct drm_i915_private {
>  
>  	struct i915_virtual_gpu vgpu;
>  
> +	struct intel_csr csr;
> +
> +	/* Display CSR-related protection */
> +	struct mutex csr_lock;

Another small one: If we have a substruct we put the lock withing that
substruct, e.g. dev_priv->psr.lock. Can you pls do another patch on top to
move that?

Thanks, 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] 37+ messages in thread

* Re: [PATCH v4 5/8] drm/i915/skl: Add DC6 Trigger sequence.
  2015-04-16  8:52 ` [PATCH v4 5/8] drm/i915/skl: Add DC6 Trigger sequence Animesh Manna
  2015-04-30 13:41   ` Imre Deak
  2015-05-04  9:44   ` Daniel Vetter
@ 2015-05-04 13:05   ` Daniel Vetter
  2 siblings, 0 replies; 37+ messages in thread
From: Daniel Vetter @ 2015-05-04 13:05 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On Thu, Apr 16, 2015 at 02:22:11PM +0530, Animesh Manna wrote:
> From: Suketu Shah <suketu.j.shah@intel.com>
> 
> Add triggers for DC6 as per details provided in skl_enable_dc6
> and skl_disable_dc6 implementations.
> 
> Also Call POSTING_READ for every write to a register to ensure
> it is written to immediately
> 
> v1: Remove POSTING_READ and intel_prepare_ddi calls as they've been added in previous patches.
> 
> v2:
> 1] Remove check for backlight disabled as it should be the case by that time.
> 2] Mark DC5 as disabled when enabling DC6.
> 3] Return from DC5-disabling function early if DC5 is already be disabled which can happen
>    due to DC6-enabling earlier.
> 3] Ensure CSR firmware is loaded after resume from DC6 as corresponding memory contents won't
>    be retained after runtime-suspend.
> 4] Ensure that CSR isn't identified as loaded before CSR-loading program is called during
>    runtime-resume.
> 
> v3: Rebase to latest
> Modified as per review comments from Imre and after discussion with Art:
> 1] DC6 should be preferably enabled when PG2 is disabled by SW as the check for PG1 being
>    disabled is taken of by HW to enter DC6, and disabled when PG2 is enabled respectively.
>    This helps save more power, especially in the case when display is disabled but GT is
>    enabled. Accordingly, replacing DC5 trigger sequence with DC6 for SKL.
> 2] DC6 could be enabled from intel_runtime_suspend() function, if DC5 is already enabled.
> 3] Move CSR-load-status setting code from intel_runtime_suspend function to a new function.
> 
> v4:
> 1] Enable/disable DC6 only when toggling the power-well using a newly defined macro ENABLE_DC6.
> 
> v5:
> 1] Load CSR on system resume too as firmware may be lost on system suspend preventing
>    enabling DC5, DC6.
> 2] DDI buffers shouldn't be programmed during driver-load/resume as it's already done
>    during modeset initialization then and also that the encoder list is still uninitialized by
>    then. Therefore, call intel_prepare_ddi function right after disabling DC6 but outside
>    skl_disable_dc6 function and not during driver-load/resume.
> 
> v6:
> 1] Rebase to latest.
> 2] Move SKL_ENABLE_DC6 macro definition from intel_display.c to intel_runtime_pm.c.
> 
> v7:
> 1) Refactored the code for removing the warning got from checkpatch.
> 2) After adding dmc ver 1.0 support rebased on top of nightly. (Animesh)
> 
> v8:
> - Reverted the changes done in v7.
> - Removed the condition check in skl_prepare_resune(). (Animesh)
> 
> Issue: VIZ-2819
> Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com>
> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com>
> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
> Signed-off-by: Animesh Manna <animesh.manna@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c         | 30 +++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 43 +++++++++++++++++++++++++++------
>  2 files changed, 66 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index acd0e2b..0f590e3 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -594,6 +594,8 @@ static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
>  static int intel_suspend_complete(struct drm_i915_private *dev_priv);
>  static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
>  			      bool rpm_resume);
> +static int skl_resume_prepare(struct drm_i915_private *dev_priv);

Please no forward declarations of static functions. I know that
vlv_resume_prepare is kinda misplaced already, but that's not a good
excuse. Can you please do another fixup patch to juggle these around?

We might even want to extract i915_suspend.c or similar (now that the ums
gunk is gone) to keep these all together. Not sure about that ...
-Daniel

> +
>  
>  static int i915_drm_suspend(struct drm_device *dev)
>  {
> @@ -808,6 +810,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
>  
>  	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
>  		hsw_disable_pc8(dev_priv);
> +	else if (IS_SKYLAKE(dev_priv))
> +		ret = skl_resume_prepare(dev_priv);
>  
>  	intel_uncore_sanitize(dev);
>  	intel_power_domains_init_hw(dev_priv);
> @@ -1022,6 +1026,19 @@ static int i915_pm_resume(struct device *dev)
>  	return i915_drm_resume(drm_dev);
>  }
>  
> +static int skl_suspend_complete(struct drm_i915_private *dev_priv)
> +{
> +	/* Enabling DC6 is not a hard requirement to enter runtime D3 */
> +
> +	/*
> +	 * This is to ensure that CSR isn't identified as loaded before
> +	 * CSR-loading program is called during runtime-resume.
> +	 */
> +	intel_csr_load_status_set(dev_priv, FW_UNINITIALIZED);
> +
> +	return 0;
> +}
> +
>  static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
>  {
>  	hsw_enable_pc8(dev_priv);
> @@ -1029,6 +1046,15 @@ static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
>  	return 0;
>  }
>  
> +static int skl_resume_prepare(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +
> +	intel_csr_load_program(dev);
> +
> +	return 0;
> +}
> +
>  /*
>   * Save all Gunit registers that may be lost after a D3 and a subsequent
>   * S0i[R123] transition. The list of registers needing a save/restore is
> @@ -1487,6 +1513,8 @@ static int intel_runtime_resume(struct device *device)
>  
>  	if (IS_GEN6(dev_priv))
>  		intel_init_pch_refclk(dev);
> +	else if (IS_SKYLAKE(dev))
> +		ret = skl_resume_prepare(dev_priv);
>  	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
>  		hsw_disable_pc8(dev_priv);
>  	else if (IS_VALLEYVIEW(dev_priv))
> @@ -1519,6 +1547,8 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv)
>  	struct drm_device *dev = dev_priv->dev;
>  	int ret;
>  
> +	if (IS_SKYLAKE(dev))
> +		ret = skl_suspend_complete(dev_priv);
>  	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
>  		ret = hsw_suspend_complete(dev_priv);
>  	else if (IS_VALLEYVIEW(dev))
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index da8c18d..7e6908e 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -49,7 +49,8 @@
>   * present for a given platform.
>   */
>  
> -#define GEN9_ENABLE_DC5(dev) (IS_SKYLAKE(dev))
> +#define GEN9_ENABLE_DC5(dev) 0
> +#define SKL_ENABLE_DC6(dev) IS_SKYLAKE(dev)
>  
>  #define for_each_power_well(i, power_well, domain_mask, power_domains)	\
>  	for (i = 0;							\
> @@ -397,6 +398,16 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
>  	POSTING_READ(DC_STATE_EN);
>  }
>  
> +static void skl_enable_dc6(struct drm_i915_private *dev_priv)
> +{
> +	/* TODO: Implementation to be done. */
> +}
> +
> +static void skl_disable_dc6(struct drm_i915_private *dev_priv)
> +{
> +	/* TODO: Implementation to be done. */
> +}
> +
>  static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  			struct i915_power_well *power_well, bool enable)
>  {
> @@ -444,9 +455,21 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  				!I915_READ(HSW_PWR_WELL_BIOS),
>  				"Invalid for power well status to be enabled, unless done by the BIOS, \
>  				when request is to disable!\n");
> -			if (GEN9_ENABLE_DC5(dev) &&
> -				power_well->data == SKL_DISP_PW_2)
> -				gen9_disable_dc5(dev_priv);
> +			if ((GEN9_ENABLE_DC5(dev) || SKL_ENABLE_DC6(dev)) &&
> +				power_well->data == SKL_DISP_PW_2) {
> +				if (SKL_ENABLE_DC6(dev)) {
> +					skl_disable_dc6(dev_priv);
> +					/*
> +					 * DDI buffer programming unnecessary during driver-load/resume
> +					 * as it's already done during modeset initialization then.
> +					 * It's also invalid here as encoder list is still uninitialized.
> +					 */
> +					if (!dev_priv->power_domains.initializing)
> +						intel_prepare_ddi(dev);
> +				} else {
> +					gen9_disable_dc5(dev_priv);
> +				}
> +			}
>  			I915_WRITE(HSW_PWR_WELL_DRIVER, tmp | req_mask);
>  		}
>  
> @@ -464,17 +487,23 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  			POSTING_READ(HSW_PWR_WELL_DRIVER);
>  			DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
>  
> -			if (GEN9_ENABLE_DC5(dev) &&
> +			if ((GEN9_ENABLE_DC5(dev) || SKL_ENABLE_DC6(dev)) &&
>  				power_well->data == SKL_DISP_PW_2) {
>  				enum csr_state state;
> -
> +				/* TODO: wait for a completion event or
> +				 * similar here instead of busy
> +				 * waiting using wait_for function.
> +				 */
>  				wait_for((state = intel_csr_load_status_get(dev_priv)) !=
>  						FW_UNINITIALIZED, 1000);
>  				if (state != FW_LOADED)
>  					DRM_ERROR("CSR firmware not ready (%d)\n",
>  							state);
>  				else
> -					gen9_enable_dc5(dev_priv);
> +					if (SKL_ENABLE_DC6(dev))
> +						skl_enable_dc6(dev_priv);
> +					else
> +						gen9_enable_dc5(dev_priv);
>  			}
>  		}
>  	}
> -- 
> 2.0.2
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
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] 37+ messages in thread

* Re: [PATCH v4 0/8] Enable DC states for skl.
  2015-04-16  8:52 [PATCH v4 0/8] Enable DC states for skl Animesh Manna
                   ` (7 preceding siblings ...)
  2015-04-16  8:52 ` [PATCH v4 8/8] drm/i915/skl: Enable runtime PM Animesh Manna
@ 2015-05-04 13:12 ` Daniel Vetter
  8 siblings, 0 replies; 37+ messages in thread
From: Daniel Vetter @ 2015-05-04 13:12 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx

On Thu, Apr 16, 2015 at 02:22:06PM +0530, Animesh Manna wrote:
> v4:
> - Removed all warning by reordering the patchsets.
> - Changed the dmc firmware file name skl_dmc_ver1.bin, followed naming conventipon as <platform>_dmc_<api-version>.bin
> 
> v3:
> MOdified the code of patch 1 and 3 based on review commets. 
> 
> v2:
> Based on review comments modified the code.
> 
> v1:
> Initial version send as RFC.
> 
> This patch series contains the implementation for enabling DC states for gen9 
> platform, specifically for skl. Few bxt specific changes will be submitted 
> separately in a different patch series which will be extended support for bxt 
> and will use major portion of the code of this patch series.
> 
> A.Sunil Kamath (3):
>   drm/i915/skl: Add support to load SKL CSR firmware.
>   drm/i915/skl: Implement enable/disable for Display C5 state.
>   Implement enable/disable for Display C6 state.
> 
> Suketu Shah (5):
>   drm/i915/skl: Add DC5 Trigger Sequence.
>   drm/i915/skl: Assert the requirements to enter or exit DC5.
>   drm/i915/skl: Add DC6 Trigger sequence.
>   drm/i915/skl: Assert the requirements to enter or exit DC6.
>   drm/i915/skl: Enable runtime PM

Ok I pulled in the entire series. A bunch of follow-up refactoring patches
are imo required for polish, plus two more things overall I've spotted:
- intel_csr.c is lacking kerneldoc for public functions, plus a high-level
  text about how the firmware loading interacts with everything else might
  be good.
- dev_priv->csr_lock doesn't document what exactly it protects and looks a
  lot like cargo-culting - it seems to abuse locking for enforcing
  ordering, which rarely works out well. But that was just a very cursory
  look, I might be mistaken.

Thanks, Daniel


> 
>  drivers/gpu/drm/i915/Makefile           |   3 +-
>  drivers/gpu/drm/i915/i915_dma.c         |  11 +-
>  drivers/gpu/drm/i915/i915_drv.c         |  50 ++++
>  drivers/gpu/drm/i915/i915_drv.h         |  27 +-
>  drivers/gpu/drm/i915/i915_reg.h         |  11 +
>  drivers/gpu/drm/i915/intel_csr.c        | 421 ++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h        |   9 +
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 199 ++++++++++++++-
>  8 files changed, 726 insertions(+), 5 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/intel_csr.c
> 
> -- 
> 2.0.2
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
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] 37+ messages in thread

end of thread, other threads:[~2015-05-04 13:09 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-16  8:52 [PATCH v4 0/8] Enable DC states for skl Animesh Manna
2015-04-16  8:52 ` [PATCH v4 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
2015-04-16  9:18   ` Damien Lespiau
2015-04-16  9:21   ` Imre Deak
2015-04-16 11:59     ` Animesh Manna
2015-04-16 11:25       ` Imre Deak
2015-04-16 14:23         ` Animesh Manna
2015-04-16 15:20           ` Imre Deak
2015-04-28 14:45   ` Imre Deak
2015-04-29 17:29     ` [PATCH v5 " Animesh Manna
2015-04-30 13:02       ` Imre Deak
2015-05-04  9:30         ` Daniel Vetter
2015-05-04 10:31           ` Imre Deak
2015-05-04 12:54       ` Daniel Vetter
2015-04-16  8:52 ` [PATCH v4 2/8] drm/i915/skl: Add DC5 Trigger Sequence Animesh Manna
2015-04-16  9:25   ` Imre Deak
2015-04-16  9:48     ` Imre Deak
2015-04-17  5:59       ` Animesh Manna
2015-04-17  7:15         ` Imre Deak
2015-04-17 14:16           ` [PATCH v5 2/2] " Animesh Manna
2015-04-30 13:18             ` Imre Deak
2015-05-04  9:39             ` Daniel Vetter
2015-04-16  8:52 ` [PATCH v4 3/8] drm/i915/skl: Implement enable/disable for Display C5 state Animesh Manna
2015-04-30 13:21   ` Imre Deak
2015-04-16  8:52 ` [PATCH v4 4/8] drm/i915/skl: Assert the requirements to enter or exit DC5 Animesh Manna
2015-04-30 13:26   ` Imre Deak
2015-04-16  8:52 ` [PATCH v4 5/8] drm/i915/skl: Add DC6 Trigger sequence Animesh Manna
2015-04-30 13:41   ` Imre Deak
2015-05-04  9:44   ` Daniel Vetter
2015-05-04 13:05   ` Daniel Vetter
2015-04-16  8:52 ` [PATCH v4 6/8] Implement enable/disable for Display C6 state Animesh Manna
2015-04-30 13:45   ` Imre Deak
2015-04-16  8:52 ` [PATCH v4 7/8] drm/i915/skl: Assert the requirements to enter or exit DC6 Animesh Manna
2015-04-16  8:52 ` [PATCH v4 8/8] drm/i915/skl: Enable runtime PM Animesh Manna
2015-04-17  1:52   ` shuang.he
2015-04-30 13:47   ` Imre Deak
2015-05-04 13:12 ` [PATCH v4 0/8] Enable DC states for skl Daniel Vetter

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.