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

Resending the patch series as suggested by Jani.

This patch series contains the implementation for enabling DC states for gen9 
platform, specifically for skl. Few bxt specific changes will be submitted 
seperately 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 sttate.
  drm/i915/skl: 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         |  12 +-
 drivers/gpu/drm/i915/i915_drv.c         |  49 +++++
 drivers/gpu/drm/i915/i915_drv.h         | 138 +++++++++++++-
 drivers/gpu/drm/i915/i915_reg.h         |  29 +++
 drivers/gpu/drm/i915/intel_csr.c        | 310 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h        |   9 +
 drivers/gpu/drm/i915/intel_runtime_pm.c | 232 ++++++++++++++++++++++--
 8 files changed, 760 insertions(+), 22 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] 46+ messages in thread

* [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware
  2015-04-01 10:49 [PATCH 0/8] Enable DC states for skl Animesh Manna
@ 2015-04-01 10:52 ` Animesh Manna
  2015-04-01 10:52   ` [PATCH 2/8] drm/i915/skl: Implement enable/disable for Display C5 sttate Animesh Manna
                     ` (7 more replies)
  2015-04-10 15:10 ` [PATCH v2 0/8] Enable DC states for skl Animesh Manna
  1 sibling, 8 replies; 46+ messages in thread
From: Animesh Manna @ 2015-04-01 10:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Animesh Manna

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)

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  |  12 +-
 drivers/gpu/drm/i915/i915_drv.c  |  20 +++
 drivers/gpu/drm/i915/i915_drv.h  | 132 ++++++++++++++++++++
 drivers/gpu/drm/i915/i915_reg.h  |  18 +++
 drivers/gpu/drm/i915/intel_csr.c | 262 +++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |   5 +
 7 files changed, 450 insertions(+), 2 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 68e0c85..4d92429 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -783,6 +783,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);
 
@@ -828,10 +829,15 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
 	intel_uncore_init(dev);
 
-	ret = i915_gem_gtt_init(dev);
+	/* Load CSR Firmware for SKL */
+	ret = intel_csr_ucode_init(dev);
 	if (ret)
 		goto out_regs;
 
+	ret = i915_gem_gtt_init(dev);
+	if (ret)
+		goto out_freecsr;
+
 	/* WARNING: Apparently we must kick fbdev drivers before vgacon,
 	 * otherwise the vga fbdev driver falls over. */
 	ret = i915_kick_out_firmware_fb(dev_priv);
@@ -1000,6 +1006,8 @@ out_mtrrfree:
 	io_mapping_free(dev_priv->gtt.mappable);
 out_gtt:
 	i915_global_gtt_cleanup(dev);
+out_freecsr:
+	intel_csr_ucode_fini(dev);
 out_regs:
 	intel_uncore_fini(dev);
 	pci_iounmap(dev->pdev, dev_priv->regs);
@@ -1077,6 +1085,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 82f8be4..489caa6 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -543,6 +543,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 4ef320c..dd572a0 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -666,6 +666,12 @@ 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 {
+	int csr_size;
+	u8 *csr_buf;
+	const char *fw_path;
+};
+
 #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
 	func(is_mobile) sep \
 	func(is_i85x) sep \
@@ -1560,6 +1566,123 @@ struct i915_virtual_gpu {
 	bool active;
 };
 
+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 intel_dmc_info {
+	__be32 *dmc_payload;
+	uint32_t dmc_fw_size;
+	uint32_t mmio_count;
+	uint32_t mmioaddr[8];
+	uint32_t mmiodata[8];
+};
+
 struct drm_i915_private {
 	struct drm_device *dev;
 	struct kmem_cache *slab;
@@ -1574,6 +1697,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_PORTS];
 
 
@@ -1832,6 +1960,7 @@ struct drm_i915_private {
 	 * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
 	 * will be rejected. Instead look for a better place.
 	 */
+	struct intel_dmc_info dmc_info;
 };
 
 static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
@@ -2418,6 +2547,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
@@ -2508,6 +2639,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/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index b522eb6..77faa2b 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -6776,6 +6776,24 @@ 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 CSR registers for DC5 and DC6
+*/
+#define CSR_PROGRAM_BASE		0x80000
+#define CSR_HEADER_OFFSET		128
+#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
+#define CSR_MAX_MMIO_COUNT		8
+
 /* 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_csr.c b/drivers/gpu/drm/i915/intel_csr.c
new file mode 100644
index 0000000..f44f1cd
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -0,0 +1,262 @@
+/*
+ * 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);
+
+#define num_array_elements(a) (sizeof(a)/sizeof(a[0]))
+
+struct stepping_info {
+	char stepping;
+	char substepping;
+	uint16_t reserved;
+};
+
+struct stepping_info skl_stepping_info[] = {
+		{'A', '0', 0}, {'B', '0', 0}, {'C', '0', 0},
+		{'D', '0', 0}, {'E', '0', 0}, {'F', '0', 0},
+		{'G', '0', 0}, {'H', '0', 0}, {'I', '0', 0}
+};
+
+char intel_get_stepping(struct drm_device *dev)
+{
+	if (IS_SKYLAKE(dev) && (dev->pdev->revision <
+			num_array_elements(skl_stepping_info)))
+		return skl_stepping_info[dev->pdev->revision].stepping;
+	else
+		return -ENODATA;
+}
+
+char intel_get_substepping(struct drm_device *dev)
+{
+	if (IS_SKYLAKE(dev) && (dev->pdev->revision <
+			num_array_elements(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;
+	unsigned char *buf = (unsigned char *)dev_priv->dmc_info.dmc_payload;
+	uint32_t i, num_bytes;
+
+	if (!IS_GEN9(dev)) {
+		DRM_ERROR("No CSR support available for this platform\n");
+		return;
+	}
+
+	mutex_lock(&dev_priv->csr_lock);
+	/* fw_size is dwords, converting it to bytes and nearest 8 multiple. */
+	num_bytes = dev_priv->dmc_info.dmc_fw_size * 4;
+	for (i = 0; i < (num_bytes & ~7); i = i + 8) {
+		uint64_t tmp = *(uint64_t *)(buf + i);
+
+		I915_WRITE64((CSR_PROGRAM_BASE + i), tmp);
+	}
+
+	/* fw_size is in dwords, for odd size need to write last 4 bytes */
+	if (num_bytes & 7) {
+		uint32_t tmp = *(uint32_t *)(buf + (num_bytes & ~7));
+
+		I915_WRITE((CSR_PROGRAM_BASE + i), tmp);
+	}
+
+	for (i = 0; i < dev_priv->dmc_info.mmio_count; i++) {
+		I915_WRITE(dev_priv->dmc_info.mmioaddr[i],
+			dev_priv->dmc_info.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, j;
+	__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;
+	}
+
+	/* save csr f/w as it will be needed during resume */
+	csr->csr_buf = kmemdup(fw->data, fw->size, GFP_KERNEL);
+
+	csr->csr_size = fw->size;
+
+	release_firmware(fw);
+
+	/* Extract CSS Header information*/
+	css_header = (struct intel_css_header *)csr->csr_buf;
+	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 *)
+					&csr->csr_buf[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 *)&csr->csr_buf[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 > CSR_MAX_MMIO_COUNT) {
+		DRM_ERROR("Firmware has wrong mmio count %u\n",
+						dmc_header->mmio_count);
+		goto out;
+	}
+	dev_priv->dmc_info.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;
+		}
+		dev_priv->dmc_info.mmioaddr[i] = dmc_header->mmioaddr[i];
+		dev_priv->dmc_info.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;
+	}
+	dev_priv->dmc_info.dmc_payload = kmalloc(nbytes, GFP_KERNEL);
+	if (!dev_priv->dmc_info.dmc_payload) {
+		DRM_ERROR("Memory allocation failed for dmc payload\n");
+		goto out;
+	}
+
+	dmc_payload = dev_priv->dmc_info.dmc_payload;
+	for (i = 0, j = 0; i < nbytes; i = i + 4, j++) {
+		uint32_t *tmp = (u32 *)&csr->csr_buf[readcount + i];
+		/*
+		 * 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[j] = cpu_to_be32(*tmp);
+	}
+
+	/* load csr program during system boot, as needed for DC states */
+	intel_csr_load_program(dev);
+out:
+	kfree(csr->csr_buf);
+	csr->csr_buf = NULL;
+}
+
+int 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 0;
+
+	if (IS_SKYLAKE(dev))
+		csr->fw_path = I915_CSR_SKL;
+	else {
+		DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
+		return 0;
+	}
+
+	/* 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);
+
+	return 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->dmc_info.dmc_payload);
+	memset(&dev_priv->dmc_info, 0, sizeof(struct intel_dmc_info));
+}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index fca7b9f..cd20b6a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1059,6 +1059,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 */
+int 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] 46+ messages in thread

* [PATCH 2/8] drm/i915/skl: Implement enable/disable for Display C5 sttate.
  2015-04-01 10:52 ` [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
@ 2015-04-01 10:52   ` Animesh Manna
  2015-04-02 15:58     ` Imre Deak
  2015-04-01 10:52   ` [PATCH 3/8] drm/i915/skl: Add DC5 Trigger Sequence Animesh Manna
                     ` (6 subsequent siblings)
  7 siblings, 1 reply; 46+ messages in thread
From: Animesh Manna @ 2015-04-01 10:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Animesh Manna

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 | 47 +++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 77faa2b..d064e95 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -6794,6 +6794,17 @@ enum skl_disp_power_wells {
 #define CSR_MMIO_END_RANGE		0x8FFFF
 #define CSR_MAX_MMIO_COUNT		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 ce00e69..bc6cee9 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -319,6 +319,53 @@ 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)
+{
+	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)
+{
+	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,
 			struct i915_power_well *power_well, bool enable)
 {
-- 
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] 46+ messages in thread

* [PATCH 3/8] drm/i915/skl: Add DC5 Trigger Sequence.
  2015-04-01 10:52 ` [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
  2015-04-01 10:52   ` [PATCH 2/8] drm/i915/skl: Implement enable/disable for Display C5 sttate Animesh Manna
@ 2015-04-01 10:52   ` Animesh Manna
  2015-04-02 19:33     ` Imre Deak
  2015-04-01 10:52   ` [PATCH 4/8] drm/i915/skl: Assert the requirements to enter or exit DC5 Animesh Manna
                     ` (5 subsequent siblings)
  7 siblings, 1 reply; 46+ messages in thread
From: Animesh Manna @ 2015-04-01 10:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Suketu Shah, Animesh Manna

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)

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         |  2 ++
 drivers/gpu/drm/i915/intel_csr.c        | 50 ++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_drv.h        |  2 ++
 drivers/gpu/drm/i915/intel_runtime_pm.c | 31 ++++++++++++++++++++
 4 files changed, 84 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index dd572a0..3320fb4 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -669,6 +669,8 @@ struct intel_uncore {
 struct intel_csr {
 	int csr_size;
 	u8 *csr_buf;
+	bool loaded;
+	bool failed;
 	const char *fw_path;
 };
 
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
index f44f1cd..87d393a 100644
--- a/drivers/gpu/drm/i915/intel_csr.c
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -60,6 +60,25 @@ char intel_get_substepping(struct drm_device *dev)
 	else
 		return -ENODATA;
 }
+
+bool intel_csr_load_status_get(struct drm_i915_private *dev_priv)
+{
+	bool val = false;
+
+	mutex_lock(&dev_priv->csr_lock);
+	val = dev_priv->csr.loaded;
+	mutex_unlock(&dev_priv->csr_lock);
+
+	return val;
+}
+
+void intel_csr_load_status_set(struct drm_i915_private *dev_priv, bool val)
+{
+	mutex_lock(&dev_priv->csr_lock);
+	dev_priv->csr.loaded = val;
+	mutex_unlock(&dev_priv->csr_lock);
+}
+
 void intel_csr_load_program(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -91,6 +110,8 @@ void intel_csr_load_program(struct drm_device *dev)
 		I915_WRITE(dev_priv->dmc_info.mmioaddr[i],
 			dev_priv->dmc_info.mmiodata[i]);
 	}
+
+	dev_priv->csr.loaded = true;
 	mutex_unlock(&dev_priv->csr_lock);
 }
 
@@ -110,11 +131,13 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 
 	if (!fw) {
 		i915_firmware_load_error_print(csr->fw_path, 0);
+		csr->failed = true;
 		goto out;
 	}
 
 	if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
 		DRM_ERROR("Unknown stepping info, firmware loading failed\n");
+		csr->failed = true;
 		goto out;
 	}
 
@@ -131,6 +154,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));
+		csr->failed = true;
 		goto out;
 	}
 	readcount += sizeof(struct intel_css_header);
@@ -142,6 +166,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));
+		csr->failed = true;
 		goto out;
 	}
 	readcount += sizeof(struct intel_package_header);
@@ -162,6 +187,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);
+		csr->failed = true;
 		goto out;
 	}
 	readcount += dmc_offset;
@@ -171,6 +197,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));
+		csr->failed = true;
 		goto out;
 	}
 	readcount += sizeof(struct intel_dmc_header);
@@ -179,6 +206,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
 	if (dmc_header->mmio_count > CSR_MAX_MMIO_COUNT) {
 		DRM_ERROR("Firmware has wrong mmio count %u\n",
 						dmc_header->mmio_count);
+		csr->failed = true;
 		goto out;
 	}
 	dev_priv->dmc_info.mmio_count = dmc_header->mmio_count;
@@ -187,6 +215,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]);
+			csr->failed = true;
 			goto out;
 		}
 		dev_priv->dmc_info.mmioaddr[i] = dmc_header->mmioaddr[i];
@@ -197,11 +226,13 @@ 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);
+		csr->failed = true;
 		goto out;
 	}
 	dev_priv->dmc_info.dmc_payload = kmalloc(nbytes, GFP_KERNEL);
 	if (!dev_priv->dmc_info.dmc_payload) {
 		DRM_ERROR("Memory allocation failed for dmc payload\n");
+		csr->failed = true;
 		goto out;
 	}
 
@@ -218,7 +249,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);
+
 out:
+	/*
+	 * Release the runtime pm reference obtained when
+	 * CSR wasn't loaded.
+	 */
+	intel_runtime_pm_put(dev_priv);
+
 	kfree(csr->csr_buf);
 	csr->csr_buf = NULL;
 }
@@ -236,16 +274,25 @@ int 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");
+		csr->failed = true;
 		return 0;
 	}
 
+	/*
+	 * 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);
+		csr->failed = true;
+	}
 
 	return ret;
 }
@@ -257,6 +304,7 @@ void intel_csr_ucode_fini(struct drm_device *dev)
 	if (!HAS_CSR(dev))
 		return;
 
+	intel_csr_load_status_set(dev_priv, false);
 	kfree(dev_priv->dmc_info.dmc_payload);
 	memset(&dev_priv->dmc_info, 0, sizeof(struct intel_dmc_info));
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index cd20b6a..39cb2dc 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1061,6 +1061,8 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
 
 /* intel_csr.c */
 int intel_csr_ucode_init(struct drm_device *dev);
+bool intel_csr_load_status_get(struct drm_i915_private *dev_priv);
+void intel_csr_load_status_set(struct drm_i915_private *dev_priv, bool val);
 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 bc6cee9..8b917e2 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 &&			\
@@ -369,6 +371,7 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
 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;
@@ -408,6 +411,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);
 		}
 
@@ -424,6 +434,27 @@ 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) {
+				if (!dev_priv->csr.failed) {
+					/*
+					* TODO: wait for a completion event or
+					* similar here instead of busy
+					* waiting using wait_for function.
+					*/
+					if (wait_for(
+						intel_csr_load_status_get(
+							dev_priv), 1000))
+						DRM_ERROR("Timed out waiting \
+							for CSR to be loaded!");
+					else
+						gen9_enable_dc5(dev_priv);
+				} else {
+					DRM_ERROR("Cannot enable DC5 as CSR \
+							failed to load!");
+				}
+			}
 		}
 	}
 
-- 
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] 46+ messages in thread

* [PATCH 4/8] drm/i915/skl: Assert the requirements to enter or exit DC5.
  2015-04-01 10:52 ` [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
  2015-04-01 10:52   ` [PATCH 2/8] drm/i915/skl: Implement enable/disable for Display C5 sttate Animesh Manna
  2015-04-01 10:52   ` [PATCH 3/8] drm/i915/skl: Add DC5 Trigger Sequence Animesh Manna
@ 2015-04-01 10:52   ` Animesh Manna
  2015-04-02 20:17     ` Imre Deak
  2015-04-01 10:52   ` [PATCH 5/8] drm/i915/skl: Implement enable/disable for Display C6 state Animesh Manna
                     ` (4 subsequent siblings)
  7 siblings, 1 reply; 46+ messages in thread
From: Animesh Manna @ 2015-04-01 10:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Suketu Shah, Animesh Manna

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)

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_drv.h        |  2 ++
 drivers/gpu/drm/i915/intel_runtime_pm.c | 61 ++++++++++++++++++++++++++++++---
 2 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 39cb2dc..9aae624 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1232,6 +1232,8 @@ void intel_power_domains_fini(struct drm_i915_private *);
 void intel_power_domains_init_hw(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_enable(struct drm_i915_private *dev_priv);
 
+bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
+				    int power_well_id);
 bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
 				    enum intel_display_power_domain domain);
 bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 8b917e2..f62d42b 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -335,12 +335,52 @@ static void gen9_set_dc_state_debugmask_memory_up(
 	}
 }
 
-static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
+static void assert_csr_loaded(struct drm_i915_private *dev_priv)
+{
+	mutex_lock(&dev_priv->csr_lock);
+
+	WARN(!dev_priv->csr.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");
+
+	mutex_unlock(&dev_priv->csr_lock);
+}
+
+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 +395,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");
 
@@ -1326,7 +1365,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;
@@ -1340,6 +1379,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 = NULL;
+	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] 46+ messages in thread

* [PATCH 5/8] drm/i915/skl: Implement enable/disable for Display C6 state.
  2015-04-01 10:52 ` [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
                     ` (2 preceding siblings ...)
  2015-04-01 10:52   ` [PATCH 4/8] drm/i915/skl: Assert the requirements to enter or exit DC5 Animesh Manna
@ 2015-04-01 10:52   ` Animesh Manna
  2015-04-02 20:20     ` Imre Deak
  2015-04-01 10:52   ` [PATCH 6/8] drm/i915/skl: Add DC6 Trigger sequence Animesh Manna
                     ` (3 subsequent siblings)
  7 siblings, 1 reply; 46+ messages in thread
From: Animesh Manna @ 2015-04-01 10:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Animesh Manna

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 | 35 +++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index f62d42b..dae65e0 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -407,6 +407,41 @@ 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)
+{
+	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)
+{
+	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);
+
+	intel_prepare_ddi(dev);
+}
+
 static void skl_set_power_well(struct drm_i915_private *dev_priv,
 			struct i915_power_well *power_well, bool enable)
 {
-- 
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] 46+ messages in thread

* [PATCH 6/8] drm/i915/skl: Add DC6 Trigger sequence.
  2015-04-01 10:52 ` [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
                     ` (3 preceding siblings ...)
  2015-04-01 10:52   ` [PATCH 5/8] drm/i915/skl: Implement enable/disable for Display C6 state Animesh Manna
@ 2015-04-01 10:52   ` Animesh Manna
  2015-04-02 20:42     ` Imre Deak
  2015-04-01 10:52   ` [PATCH 7/8] drm/i915/skl: Assert the requirements to enter or exit DC6 Animesh Manna
                     ` (2 subsequent siblings)
  7 siblings, 1 reply; 46+ messages in thread
From: Animesh Manna @ 2015-04-01 10:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Suketu Shah, Animesh Manna

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)

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         | 29 ++++++++++
 drivers/gpu/drm/i915/i915_drv.h         |  1 +
 drivers/gpu/drm/i915/intel_runtime_pm.c | 98 +++++++++++++++++----------------
 3 files changed, 81 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 489caa6..352c7702 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -795,6 +795,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);
@@ -1009,6 +1011,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, false);
+
+	return 0;
+}
+
 static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
 {
 	hsw_enable_pc8(dev_priv);
@@ -1016,6 +1031,16 @@ static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
 	return 0;
 }
 
+int skl_resume_prepare(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+
+	if (!intel_csr_load_status_get(dev_priv))
+		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
@@ -1484,6 +1509,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))
@@ -1516,6 +1543,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/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3320fb4..5dd8d61 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2642,6 +2642,7 @@ 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);
+int skl_resume_prepare(struct drm_i915_private *dev_priv);
 
 /* i915_irq.c */
 void i915_queue_hangcheck(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 dae65e0..cc94503 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;							\
@@ -373,7 +374,7 @@ static void assert_can_disable_dc5(struct drm_i915_private *dev_priv)
 
 	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");
+		"Platform is runtime-suspended, should not disable DC5.\n");
 }
 
 static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
@@ -438,8 +439,6 @@ static void skl_disable_dc6(struct drm_i915_private *dev_priv)
 	val &= ~DC_STATE_EN_UPTO_DC6;
 	I915_WRITE(DC_STATE_EN, val);
 	POSTING_READ(DC_STATE_EN);
-
-	intel_prepare_ddi(dev);
 }
 
 static void skl_set_power_well(struct drm_i915_private *dev_priv,
@@ -483,55 +482,60 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
 	state_mask = SKL_POWER_WELL_STATE(power_well->data);
 	is_enabled = tmp & state_mask;
 
-	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);
+	if (enable && (!enable_requested)) {
+		WARN(is_enabled && !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 (SKL_ENABLE_DC6(dev) && power_well->data == SKL_DISP_PW_2) {
+			skl_disable_dc6(dev_priv);
+			/*
+			 * DDI buffer programming unnecessary during driver
+			 * load/resumeas 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);
 		}
-
-		if (!is_enabled) {
-			DRM_DEBUG_KMS("Enabling %s\n", power_well->name);
-			if (wait_for((I915_READ(HSW_PWR_WELL_DRIVER) &
-				state_mask), 1))
-				DRM_ERROR("%s enable timeout\n",
-					power_well->name);
+		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);
+	}
+	if (enable && (!is_enabled)) {
+		DRM_DEBUG_KMS("Enabling %s\n", power_well->name);
+		if (wait_for((I915_READ(HSW_PWR_WELL_DRIVER) & state_mask), 1))
+			DRM_ERROR("%s enable timeout\n", power_well->name);
 			check_fuse_status = true;
-		}
-	} else {
-		if (enable_requested) {
-			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) {
-				if (!dev_priv->csr.failed) {
-					/*
-					* TODO: wait for a completion event or
-					* similar here instead of busy
-					* waiting using wait_for function.
-					*/
-					if (wait_for(
-						intel_csr_load_status_get(
-							dev_priv), 1000))
-						DRM_ERROR("Timed out waiting \
-							for CSR to be loaded!");
-					else
-						gen9_enable_dc5(dev_priv);
-				} else {
-					DRM_ERROR("Cannot enable DC5 as CSR \
-							failed to load!");
-				}
+	}
+	if ((!enable) && enable_requested) {
+		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) || SKL_ENABLE_DC6(dev)) &&
+			power_well->data == SKL_DISP_PW_2) {
+			if (dev_priv->csr.failed) {
+				DRM_ERROR("CSR loading failed, not entering %s",
+				SKL_ENABLE_DC6(dev) ? "DC6" : "DC5");
+				goto exit;
+			}
+			/*
+			 * TODO: wait for a completion event or similar here
+			 * instead of busy waiting using wait_for function.
+			 */
+			if (wait_for(intel_csr_load_status_get(dev_priv),
+								1000)) {
+				DRM_ERROR("Timed out for CSR loading!");
+				goto exit;
 			}
+			if (SKL_ENABLE_DC6(dev))
+				skl_enable_dc6(dev_priv);
+			else
+				gen9_enable_dc5(dev_priv);
 		}
 	}
 
+exit:
 	if (check_fuse_status) {
 		if (power_well->data == SKL_DISP_PW_1) {
 			if (wait_for((I915_READ(SKL_FUSE_STATUS) &
-- 
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] 46+ messages in thread

* [PATCH 7/8] drm/i915/skl: Assert the requirements to enter or exit DC6.
  2015-04-01 10:52 ` [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
                     ` (4 preceding siblings ...)
  2015-04-01 10:52   ` [PATCH 6/8] drm/i915/skl: Add DC6 Trigger sequence Animesh Manna
@ 2015-04-01 10:52   ` Animesh Manna
  2015-04-02 20:49     ` Imre Deak
  2015-04-01 10:52   ` [PATCH 8/8] drm/i915/skl: Enable runtime PM Animesh Manna
  2015-04-02 15:21   ` [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware Imre Deak
  7 siblings, 1 reply; 46+ messages in thread
From: Animesh Manna @ 2015-04-01 10:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Suketu Shah, Animesh Manna

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)

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_runtime_pm.c | 38 +++++++++++++++++++++++++++------
 1 file changed, 32 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index cc94503..9196de3 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -1,5 +1,5 @@
-/*
- * Copyright © 2012-2014 Intel Corporation
+		/*
+ * Cipyright © 2012-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"),
@@ -408,12 +408,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");
 
@@ -428,10 +455,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] 46+ messages in thread

* [PATCH 8/8] drm/i915/skl: Enable runtime PM
  2015-04-01 10:52 ` [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
                     ` (5 preceding siblings ...)
  2015-04-01 10:52   ` [PATCH 7/8] drm/i915/skl: Assert the requirements to enter or exit DC6 Animesh Manna
@ 2015-04-01 10:52   ` Animesh Manna
  2015-04-02 20:49     ` Imre Deak
  2015-04-02 15:21   ` [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware Imre Deak
  7 siblings, 1 reply; 46+ messages in thread
From: Animesh Manna @ 2015-04-01 10:52 UTC (permalink / raw)
  To: intel-gfx; +Cc: Suketu Shah, Animesh Manna

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 5dd8d61..e5fc1de 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2545,7 +2545,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] 46+ messages in thread

* Re: [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware
  2015-04-01 10:52 ` [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
                     ` (6 preceding siblings ...)
  2015-04-01 10:52   ` [PATCH 8/8] drm/i915/skl: Enable runtime PM Animesh Manna
@ 2015-04-02 15:21   ` Imre Deak
  2015-04-10 15:11     ` [PATCH v2 " Animesh Manna
  7 siblings, 1 reply; 46+ messages in thread
From: Imre Deak @ 2015-04-02 15:21 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx

On ke, 2015-04-01 at 16:22 +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)
> 
> 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  |  12 +-
>  drivers/gpu/drm/i915/i915_drv.c  |  20 +++
>  drivers/gpu/drm/i915/i915_drv.h  | 132 ++++++++++++++++++++
>  drivers/gpu/drm/i915/i915_reg.h  |  18 +++
>  drivers/gpu/drm/i915/intel_csr.c | 262 +++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h |   5 +
>  7 files changed, 450 insertions(+), 2 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 68e0c85..4d92429 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -783,6 +783,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);
>  
> @@ -828,10 +829,15 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  
>  	intel_uncore_init(dev);
>  
> -	ret = i915_gem_gtt_init(dev);
> +	/* Load CSR Firmware for SKL */
> +	ret = intel_csr_ucode_init(dev);
>  	if (ret)
>  		goto out_regs;

I missed this earlier, but we should just continue here in case of error
and don't fail loading the driver.

>  
> +	ret = i915_gem_gtt_init(dev);
> +	if (ret)
> +		goto out_freecsr;
> +
>  	/* WARNING: Apparently we must kick fbdev drivers before vgacon,
>  	 * otherwise the vga fbdev driver falls over. */
>  	ret = i915_kick_out_firmware_fb(dev_priv);
> @@ -1000,6 +1006,8 @@ out_mtrrfree:
>  	io_mapping_free(dev_priv->gtt.mappable);
>  out_gtt:
>  	i915_global_gtt_cleanup(dev);
> +out_freecsr:
> +	intel_csr_ucode_fini(dev);
>  out_regs:
>  	intel_uncore_fini(dev);
>  	pci_iounmap(dev->pdev, dev_priv->regs);
> @@ -1077,6 +1085,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 82f8be4..489caa6 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -543,6 +543,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 4ef320c..dd572a0 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -666,6 +666,12 @@ 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 {
> +	int csr_size;
> +	u8 *csr_buf;

csr_size isn't used and csr_buf is only used locally, so they can be
removed from here.

> +	const char *fw_path;
> +};
> +
>  #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
>  	func(is_mobile) sep \
>  	func(is_i85x) sep \
> @@ -1560,6 +1566,123 @@ struct i915_virtual_gpu {
>  	bool active;
>  };
>  
> +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;

All the above __packed structs are used only in intel_csr.c, so they can
be defined there without export them.

> +
> +struct intel_dmc_info {
> +	__be32 *dmc_payload;
> +	uint32_t dmc_fw_size;
> +	uint32_t mmio_count;
> +	uint32_t mmioaddr[8];
> +	uint32_t mmiodata[8];
> +};
> +
>  struct drm_i915_private {
>  	struct drm_device *dev;
>  	struct kmem_cache *slab;
> @@ -1574,6 +1697,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_PORTS];
>  
> 
> @@ -1832,6 +1960,7 @@ struct drm_i915_private {
>  	 * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
>  	 * will be rejected. Instead look for a better place.
>  	 */
> +	struct intel_dmc_info dmc_info;

This should be part of struct intel_csr.

>  };
>  
>  static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
> @@ -2418,6 +2547,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
> @@ -2508,6 +2639,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/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index b522eb6..77faa2b 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -6776,6 +6776,24 @@ 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 CSR registers for DC5 and DC6
> +*/
> +#define CSR_PROGRAM_BASE		0x80000
> +#define CSR_HEADER_OFFSET		128
> +#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

All of the above are used only intel_csr.c, so no need to export them.

> +#define CSR_MAX_MMIO_COUNT		8

I wouldn't define this, just use ARRAY_SIZE for the corresponding sanity
check.

> +
>  /* 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_csr.c b/drivers/gpu/drm/i915/intel_csr.c
> new file mode 100644
> index 0000000..f44f1cd
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_csr.c
> @@ -0,0 +1,262 @@
> +/*
> + * 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);
> +
> +#define num_array_elements(a) (sizeof(a)/sizeof(a[0]))

You can use ARRAY_SIZE.

> +
> +struct stepping_info {
> +	char stepping;
> +	char substepping;
> +	uint16_t reserved;

reserved is not used. 

> +};
> +
> +struct stepping_info skl_stepping_info[] = {
> +		{'A', '0', 0}, {'B', '0', 0}, {'C', '0', 0},
> +		{'D', '0', 0}, {'E', '0', 0}, {'F', '0', 0},
> +		{'G', '0', 0}, {'H', '0', 0}, {'I', '0', 0}
> +};

Should be static.

> +
> +char intel_get_stepping(struct drm_device *dev)
> +{
> +	if (IS_SKYLAKE(dev) && (dev->pdev->revision <
> +			num_array_elements(skl_stepping_info)))
> +		return skl_stepping_info[dev->pdev->revision].stepping;
> +	else
> +		return -ENODATA;
> +}
> +
> +char intel_get_substepping(struct drm_device *dev)
> +{
> +	if (IS_SKYLAKE(dev) && (dev->pdev->revision <
> +			num_array_elements(skl_stepping_info)))
> +		return skl_stepping_info[dev->pdev->revision].substepping;
> +	else
> +		return -ENODATA;
> +}
> +void intel_csr_load_program(struct drm_device *dev)

The above 3 functions should be static.

> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	unsigned char *buf = (unsigned char *)dev_priv->dmc_info.dmc_payload;
> +	uint32_t i, num_bytes;
> +
> +	if (!IS_GEN9(dev)) {
> +		DRM_ERROR("No CSR support available for this platform\n");
> +		return;
> +	}
> +
> +	mutex_lock(&dev_priv->csr_lock);
> +	/* fw_size is dwords, converting it to bytes and nearest 8 multiple. */
> +	num_bytes = dev_priv->dmc_info.dmc_fw_size * 4;
> +	for (i = 0; i < (num_bytes & ~7); i = i + 8) {
> +		uint64_t tmp = *(uint64_t *)(buf + i);
> +
> +		I915_WRITE64((CSR_PROGRAM_BASE + i), tmp);
> +	}
> +
> +	/* fw_size is in dwords, for odd size need to write last 4 bytes */
> +	if (num_bytes & 7) {
> +		uint32_t tmp = *(uint32_t *)(buf + (num_bytes & ~7));
> +
> +		I915_WRITE((CSR_PROGRAM_BASE + i), tmp);
> +	}

I wouldn't optimize at this point, just use a simple loop:
for (i = 0; i < dmc_fw_size; i++)
	I915_WRITE(CSR_PROGRAM_BASE + i * 4, (u32 __force)dmc_payload +  i);

If it needs to be optimized I'd use instead:
/* No forcewake needed for the CSR program MMIO range */
memcpy_toio(dev_priv->regs + CSR_PROGRAM_BASE, dmc_payload, dmc_fw_size * 4);

> +
> +	for (i = 0; i < dev_priv->dmc_info.mmio_count; i++) {
> +		I915_WRITE(dev_priv->dmc_info.mmioaddr[i],
> +			dev_priv->dmc_info.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, j;
> +	__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;
> +	}
> +
> +	/* save csr f/w as it will be needed during resume */
> +	csr->csr_buf = kmemdup(fw->data, fw->size, GFP_KERNEL);

Since you will copy everything relevant out of csr_buf and free it at
the end of the function, you could just use fw->data directly (and move
release_firmware later accordingly).

> +
> +	csr->csr_size = fw->size;

This is unused.

> +
> +	release_firmware(fw);
> +
> +	/* Extract CSS Header information*/
> +	css_header = (struct intel_css_header *)csr->csr_buf;
> +	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 *)
> +					&csr->csr_buf[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 *)&csr->csr_buf[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 > CSR_MAX_MMIO_COUNT) {
> +		DRM_ERROR("Firmware has wrong mmio count %u\n",
> +						dmc_header->mmio_count);
> +		goto out;
> +	}
> +	dev_priv->dmc_info.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;
> +		}
> +		dev_priv->dmc_info.mmioaddr[i] = dmc_header->mmioaddr[i];
> +		dev_priv->dmc_info.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;
> +	}
> +	dev_priv->dmc_info.dmc_payload = kmalloc(nbytes, GFP_KERNEL);
> +	if (!dev_priv->dmc_info.dmc_payload) {
> +		DRM_ERROR("Memory allocation failed for dmc payload\n");
> +		goto out;
> +	}
> +
> +	dmc_payload = dev_priv->dmc_info.dmc_payload;
> +	for (i = 0, j = 0; i < nbytes; i = i + 4, j++) {

I'd just use a single iterator here.

> +		uint32_t *tmp = (u32 *)&csr->csr_buf[readcount + i];
> +		/*
> +		 * 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[j] = cpu_to_be32(*tmp);
> +	}
> +
> +	/* load csr program during system boot, as needed for DC states */
> +	intel_csr_load_program(dev);
> +out:
> +	kfree(csr->csr_buf);
> +	csr->csr_buf = NULL;
> +}
> +
> +int intel_csr_ucode_init(struct drm_device *dev)

This could be void, since we won't use the returned error.

> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_csr *csr = &dev_priv->csr;
> +	int ret;
> +
> +	if (!HAS_CSR(dev))
> +		return 0;
> +
> +	if (IS_SKYLAKE(dev))
> +		csr->fw_path = I915_CSR_SKL;
> +	else {
> +		DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
> +		return 0;
> +	}
> +
> +	/* 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);
> +
> +	return 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->dmc_info.dmc_payload);
> +	memset(&dev_priv->dmc_info, 0, sizeof(struct intel_dmc_info));

No need for the memset, dmc_info won't be used afterwards.

> +}
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index fca7b9f..cd20b6a 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1059,6 +1059,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 */
> +int 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] 46+ messages in thread

* Re: [PATCH 2/8] drm/i915/skl: Implement enable/disable for Display C5 sttate.
  2015-04-01 10:52   ` [PATCH 2/8] drm/i915/skl: Implement enable/disable for Display C5 sttate Animesh Manna
@ 2015-04-02 15:58     ` Imre Deak
  2015-04-13 13:17       ` Damien Lespiau
  0 siblings, 1 reply; 46+ messages in thread
From: Imre Deak @ 2015-04-02 15:58 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx

On ke, 2015-04-01 at 16: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 | 47 +++++++++++++++++++++++++++++++++
>  2 files changed, 58 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 77faa2b..d064e95 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -6794,6 +6794,17 @@ enum skl_disp_power_wells {
>  #define CSR_MMIO_END_RANGE		0x8FFFF
>  #define CSR_MAX_MMIO_COUNT		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 ce00e69..bc6cee9 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -319,6 +319,53 @@ 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)
> +{
> +	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)
> +{
> +	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,
>  			struct i915_power_well *power_well, bool enable)
>  {


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

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

* Re: [PATCH 3/8] drm/i915/skl: Add DC5 Trigger Sequence.
  2015-04-01 10:52   ` [PATCH 3/8] drm/i915/skl: Add DC5 Trigger Sequence Animesh Manna
@ 2015-04-02 19:33     ` Imre Deak
  2015-04-10 15:11       ` [PATCH v2 " Animesh Manna
  0 siblings, 1 reply; 46+ messages in thread
From: Imre Deak @ 2015-04-02 19:33 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On Wed, 2015-04-01 at 16: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)
> 
> 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         |  2 ++
>  drivers/gpu/drm/i915/intel_csr.c        | 50 ++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_drv.h        |  2 ++
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 31 ++++++++++++++++++++
>  4 files changed, 84 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index dd572a0..3320fb4 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -669,6 +669,8 @@ struct intel_uncore {
>  struct intel_csr {
>  	int csr_size;
>  	u8 *csr_buf;
> +	bool loaded;
> +	bool failed;

Nitpick: just using an enum with loading, loaded, failed states would be
clearer.

>  	const char *fw_path;
>  };
>  
> diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
> index f44f1cd..87d393a 100644
> --- a/drivers/gpu/drm/i915/intel_csr.c
> +++ b/drivers/gpu/drm/i915/intel_csr.c
> @@ -60,6 +60,25 @@ char intel_get_substepping(struct drm_device *dev)
>  	else
>  		return -ENODATA;
>  }
> +
> +bool intel_csr_load_status_get(struct drm_i915_private *dev_priv)
> +{
> +	bool val = false;
> +
> +	mutex_lock(&dev_priv->csr_lock);
> +	val = dev_priv->csr.loaded;
> +	mutex_unlock(&dev_priv->csr_lock);
> +
> +	return val;
> +}
> +
> +void intel_csr_load_status_set(struct drm_i915_private *dev_priv, bool val)
> +{
> +	mutex_lock(&dev_priv->csr_lock);
> +	dev_priv->csr.loaded = val;
> +	mutex_unlock(&dev_priv->csr_lock);
> +}
> +
>  void intel_csr_load_program(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -91,6 +110,8 @@ void intel_csr_load_program(struct drm_device *dev)
>  		I915_WRITE(dev_priv->dmc_info.mmioaddr[i],
>  			dev_priv->dmc_info.mmiodata[i]);
>  	}
> +
> +	dev_priv->csr.loaded = true;
>  	mutex_unlock(&dev_priv->csr_lock);
>  }
>  
> @@ -110,11 +131,13 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  
>  	if (!fw) {
>  		i915_firmware_load_error_print(csr->fw_path, 0);
> +		csr->failed = true;
>  		goto out;
>  	}
>  
>  	if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
>  		DRM_ERROR("Unknown stepping info, firmware loading failed\n");
> +		csr->failed = true;
>  		goto out;
>  	}
>  
> @@ -131,6 +154,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));
> +		csr->failed = true;
>  		goto out;
>  	}
>  	readcount += sizeof(struct intel_css_header);
> @@ -142,6 +166,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));
> +		csr->failed = true;
>  		goto out;
>  	}
>  	readcount += sizeof(struct intel_package_header);
> @@ -162,6 +187,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);
> +		csr->failed = true;
>  		goto out;
>  	}
>  	readcount += dmc_offset;
> @@ -171,6 +197,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));
> +		csr->failed = true;
>  		goto out;
>  	}
>  	readcount += sizeof(struct intel_dmc_header);
> @@ -179,6 +206,7 @@ static void finish_csr_load(const struct firmware *fw, void *context)
>  	if (dmc_header->mmio_count > CSR_MAX_MMIO_COUNT) {
>  		DRM_ERROR("Firmware has wrong mmio count %u\n",
>  						dmc_header->mmio_count);
> +		csr->failed = true;
>  		goto out;
>  	}
>  	dev_priv->dmc_info.mmio_count = dmc_header->mmio_count;
> @@ -187,6 +215,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]);
> +			csr->failed = true;
>  			goto out;
>  		}
>  		dev_priv->dmc_info.mmioaddr[i] = dmc_header->mmioaddr[i];
> @@ -197,11 +226,13 @@ 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);
> +		csr->failed = true;
>  		goto out;
>  	}
>  	dev_priv->dmc_info.dmc_payload = kmalloc(nbytes, GFP_KERNEL);
>  	if (!dev_priv->dmc_info.dmc_payload) {
>  		DRM_ERROR("Memory allocation failed for dmc payload\n");
> +		csr->failed = true;
>  		goto out;
>  	}

Nitpick: the above could be simplified by setting the state to 'failed'
once on the top and to 'loaded' in intel_csr_load_program.

>  
> @@ -218,7 +249,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);
> +
>  out:
> +	/*
> +	 * Release the runtime pm reference obtained when
> +	 * CSR wasn't loaded.
> +	 */
> +	intel_runtime_pm_put(dev_priv);
> +
>  	kfree(csr->csr_buf);
>  	csr->csr_buf = NULL;
>  }
> @@ -236,16 +274,25 @@ int 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");
> +		csr->failed = true;
>  		return 0;
>  	}
>  
> +	/*
> +	 * 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);
> +		csr->failed = true;
> +	}
>  
>  	return ret;
>  }
> @@ -257,6 +304,7 @@ void intel_csr_ucode_fini(struct drm_device *dev)
>  	if (!HAS_CSR(dev))
>  		return;
>  
> +	intel_csr_load_status_set(dev_priv, false);
>  	kfree(dev_priv->dmc_info.dmc_payload);
>  	memset(&dev_priv->dmc_info, 0, sizeof(struct intel_dmc_info));
>  }
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index cd20b6a..39cb2dc 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1061,6 +1061,8 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
>  
>  /* intel_csr.c */
>  int intel_csr_ucode_init(struct drm_device *dev);
> +bool intel_csr_load_status_get(struct drm_i915_private *dev_priv);
> +void intel_csr_load_status_set(struct drm_i915_private *dev_priv, bool val);
>  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 bc6cee9..8b917e2 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 &&			\
> @@ -369,6 +371,7 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
>  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;
> @@ -408,6 +411,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");

This would look ugly in dmesg. You don't need to break the string, the
80 character limit doesn't apply here. I would also just leave out the
message part, the condition itself is self descriptive.

> +			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);
>  		}
>  
> @@ -424,6 +434,27 @@ 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) {
> +				if (!dev_priv->csr.failed) {
> +					/*
> +					* TODO: wait for a completion event or
> +					* similar here instead of busy
> +					* waiting using wait_for function.
> +					*/
> +					if (wait_for(
> +						intel_csr_load_status_get(
> +							dev_priv), 1000))
> +						DRM_ERROR("Timed out waiting \
> +							for CSR to be loaded!");
> +					else
> +						gen9_enable_dc5(dev_priv);
> +				} else {
> +					DRM_ERROR("Cannot enable DC5 as CSR \
> +							failed to load!");

Again, the above error messages shouldn't be broken into multiple lines.

With the above fixed (not considering the nitpicks), this is:
Reviewed-by: Imre Deak <imre.deak@intel.com>

> +				}
> +			}
>  		}
>  	}
>  


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

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

* Re: [PATCH 4/8] drm/i915/skl: Assert the requirements to enter or exit DC5.
  2015-04-01 10:52   ` [PATCH 4/8] drm/i915/skl: Assert the requirements to enter or exit DC5 Animesh Manna
@ 2015-04-02 20:17     ` Imre Deak
  2015-04-10 15:11       ` [PATCH v2 " Animesh Manna
  0 siblings, 1 reply; 46+ messages in thread
From: Imre Deak @ 2015-04-02 20:17 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On Wed, 2015-04-01 at 16: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)
> 
> 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_drv.h        |  2 ++
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 61 ++++++++++++++++++++++++++++++---
>  2 files changed, 58 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 39cb2dc..9aae624 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1232,6 +1232,8 @@ void intel_power_domains_fini(struct drm_i915_private *);
>  void intel_power_domains_init_hw(struct drm_i915_private *dev_priv);
>  void intel_runtime_pm_enable(struct drm_i915_private *dev_priv);
>  
> +bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
> +				    int power_well_id);

I haven't seen this being used outside of intel_runtime_pm, so no need
to export it.

>  bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
>  				    enum intel_display_power_domain domain);
>  bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 8b917e2..f62d42b 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -335,12 +335,52 @@ static void gen9_set_dc_state_debugmask_memory_up(
>  	}
>  }
>  
> -static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
> +static void assert_csr_loaded(struct drm_i915_private *dev_priv)
> +{
> +	mutex_lock(&dev_priv->csr_lock);

No point in taking the lock here.

> +
> +	WARN(!dev_priv->csr.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");
> +
> +	mutex_unlock(&dev_priv->csr_lock);
> +}
> +
> +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 +395,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");
>  
> @@ -1326,7 +1365,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)

power_well_id can refer to some other power well besides one in punit,
so we should keep this as int.

>  {
>  	struct i915_power_domains *power_domains = &dev_priv->power_domains;
>  	struct i915_power_well *power_well;
> @@ -1340,6 +1379,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 = NULL;

No need to initialize this.

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

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

* Re: [PATCH 5/8] drm/i915/skl: Implement enable/disable for Display C6 state.
  2015-04-01 10:52   ` [PATCH 5/8] drm/i915/skl: Implement enable/disable for Display C6 state Animesh Manna
@ 2015-04-02 20:20     ` Imre Deak
  0 siblings, 0 replies; 46+ messages in thread
From: Imre Deak @ 2015-04-02 20:20 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx

On Wed, 2015-04-01 at 16: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 | 35 +++++++++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index f62d42b..dae65e0 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -407,6 +407,41 @@ 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)
> +{
> +	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)
> +{
> +	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);
> +
> +	intel_prepare_ddi(dev);
> +}
> +
>  static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  			struct i915_power_well *power_well, bool enable)
>  {


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

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

* Re: [PATCH 6/8] drm/i915/skl: Add DC6 Trigger sequence.
  2015-04-01 10:52   ` [PATCH 6/8] drm/i915/skl: Add DC6 Trigger sequence Animesh Manna
@ 2015-04-02 20:42     ` Imre Deak
  2015-04-10 15:11       ` [PATCH v2 " Animesh Manna
  0 siblings, 1 reply; 46+ messages in thread
From: Imre Deak @ 2015-04-02 20:42 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On Wed, 2015-04-01 at 16: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)
> 
> 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         | 29 ++++++++++
>  drivers/gpu/drm/i915/i915_drv.h         |  1 +
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 98 +++++++++++++++++----------------
>  3 files changed, 81 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 489caa6..352c7702 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -795,6 +795,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);
> @@ -1009,6 +1011,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, false);
> +
> +	return 0;
> +}
> +
>  static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
>  {
>  	hsw_enable_pc8(dev_priv);
> @@ -1016,6 +1031,16 @@ static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
>  	return 0;
>  }
>  
> +int skl_resume_prepare(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +
> +	if (!intel_csr_load_status_get(dev_priv))

No need to check the above, it's guaranteed the firmware is not loaded
at this point.

> +		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
> @@ -1484,6 +1509,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))
> @@ -1516,6 +1543,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/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 3320fb4..5dd8d61 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2642,6 +2642,7 @@ 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);
> +int skl_resume_prepare(struct drm_i915_private *dev_priv);

No need to export this, you can add a forward declaration at the top in
i915_drv.c.

>  
>  /* i915_irq.c */
>  void i915_queue_hangcheck(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 dae65e0..cc94503 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;							\
> @@ -373,7 +374,7 @@ static void assert_can_disable_dc5(struct drm_i915_private *dev_priv)
>  
>  	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");
> +		"Platform is runtime-suspended, should not disable DC5.\n");
>  }
>  
>  static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
> @@ -438,8 +439,6 @@ static void skl_disable_dc6(struct drm_i915_private *dev_priv)
>  	val &= ~DC_STATE_EN_UPTO_DC6;
>  	I915_WRITE(DC_STATE_EN, val);
>  	POSTING_READ(DC_STATE_EN);
> -
> -	intel_prepare_ddi(dev);
>  }
>  
>  static void skl_set_power_well(struct drm_i915_private *dev_priv,
> @@ -483,55 +482,60 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv,
>  	state_mask = SKL_POWER_WELL_STATE(power_well->data);
>  	is_enabled = tmp & state_mask;
>  
> -	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);
> +	if (enable && (!enable_requested)) {
> +		WARN(is_enabled && !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 (SKL_ENABLE_DC6(dev) && power_well->data == SKL_DISP_PW_2) {
> +			skl_disable_dc6(dev_priv);
> +			/*
> +			 * DDI buffer programming unnecessary during driver
> +			 * load/resumeas it's already done during modeset
> +			 * initialization then. It's also invalid here as
> +			 * encoder list is still uninitialized.

Some typos in the above comment.

> +			 */
> +			if (!dev_priv->power_domains.initializing)
> +				intel_prepare_ddi(dev);
>  		}
> -
> -		if (!is_enabled) {
> -			DRM_DEBUG_KMS("Enabling %s\n", power_well->name);
> -			if (wait_for((I915_READ(HSW_PWR_WELL_DRIVER) &
> -				state_mask), 1))
> -				DRM_ERROR("%s enable timeout\n",
> -					power_well->name);
> +		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);
> +	}
> +	if (enable && (!is_enabled)) {
> +		DRM_DEBUG_KMS("Enabling %s\n", power_well->name);
> +		if (wait_for((I915_READ(HSW_PWR_WELL_DRIVER) & state_mask), 1))
> +			DRM_ERROR("%s enable timeout\n", power_well->name);
>  			check_fuse_status = true;
> -		}
> -	} else {
> -		if (enable_requested) {
> -			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) {
> -				if (!dev_priv->csr.failed) {
> -					/*
> -					* TODO: wait for a completion event or
> -					* similar here instead of busy
> -					* waiting using wait_for function.
> -					*/
> -					if (wait_for(
> -						intel_csr_load_status_get(
> -							dev_priv), 1000))
> -						DRM_ERROR("Timed out waiting \
> -							for CSR to be loaded!");
> -					else
> -						gen9_enable_dc5(dev_priv);
> -				} else {
> -					DRM_ERROR("Cannot enable DC5 as CSR \
> -							failed to load!");
> -				}
> +	}
> +	if ((!enable) && enable_requested) {
> +		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) || SKL_ENABLE_DC6(dev)) &&
> +			power_well->data == SKL_DISP_PW_2) {
> +			if (dev_priv->csr.failed) {
> +				DRM_ERROR("CSR loading failed, not entering %s",
> +				SKL_ENABLE_DC6(dev) ? "DC6" : "DC5");
> +				goto exit;
> +			}
> +			/*
> +			 * TODO: wait for a completion event or similar here
> +			 * instead of busy waiting using wait_for function.
> +			 */
> +			if (wait_for(intel_csr_load_status_get(dev_priv),
> +								1000)) {
> +				DRM_ERROR("Timed out for CSR loading!");
> +				goto exit;
>  			}
> +			if (SKL_ENABLE_DC6(dev))
> +				skl_enable_dc6(dev_priv);
> +			else
> +				gen9_enable_dc5(dev_priv);
>  		}
>  	}
>  
> +exit:
>  	if (check_fuse_status) {
>  		if (power_well->data == SKL_DISP_PW_1) {
>  			if (wait_for((I915_READ(SKL_FUSE_STATUS) &

No need to change anything about this now, but there are a quite a lot
of rewrites here for things that were added earlier in the patchset and
there is really no good reason for this. In the future it would make the
review easier if you would squash/organize the patches so as to minimize
such rewrites.

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

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

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

* Re: [PATCH 7/8] drm/i915/skl: Assert the requirements to enter or exit DC6.
  2015-04-01 10:52   ` [PATCH 7/8] drm/i915/skl: Assert the requirements to enter or exit DC6 Animesh Manna
@ 2015-04-02 20:49     ` Imre Deak
  2015-04-10 15:12       ` [PATCH v2 " Animesh Manna
  0 siblings, 1 reply; 46+ messages in thread
From: Imre Deak @ 2015-04-02 20:49 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On Wed, 2015-04-01 at 16:22 +0530, Animesh Manna wrote:
> 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)
> 
> 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_runtime_pm.c | 38 +++++++++++++++++++++++++++------
>  1 file changed, 32 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index cc94503..9196de3 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -1,5 +1,5 @@
> -/*
> - * Copyright © 2012-2014 Intel Corporation
> +		/*
> + * Cipyright © 2012-2014 Intel Corporation

Unintentional change.

>   *
>   * Permission is hereby granted, free of charge, to any person obtaining a
>   * copy of this software and associated documentation files (the "Software"),
> @@ -408,12 +408,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;

I missed this earlier, but this early return should also be added to
assert_can_disable_dc5().

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

> +
> +	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");
>  
> @@ -428,10 +455,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");
>  


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

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

* Re: [PATCH 8/8] drm/i915/skl: Enable runtime PM
  2015-04-01 10:52   ` [PATCH 8/8] drm/i915/skl: Enable runtime PM Animesh Manna
@ 2015-04-02 20:49     ` Imre Deak
  0 siblings, 0 replies; 46+ messages in thread
From: Imre Deak @ 2015-04-02 20:49 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On Wed, 2015-04-01 at 16: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 5dd8d61..e5fc1de 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2545,7 +2545,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] 46+ messages in thread

* [PATCH v2 0/8] Enable DC states for skl.
  2015-04-01 10:49 [PATCH 0/8] Enable DC states for skl Animesh Manna
  2015-04-01 10:52 ` [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
@ 2015-04-10 15:10 ` Animesh Manna
  1 sibling, 0 replies; 46+ messages in thread
From: Animesh Manna @ 2015-04-10 15:10 UTC (permalink / raw)
  To: intel-gfx

v2: Refactored the code based on review comments.

v1:
This patch series contains the implementation for enabling DC states for gen9 
platform, specifically for skl. Few bxt specific changes will be submitted 
seperately 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 sttate.
  drm/i915/skl: 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         |  13 +-
 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        | 281 ++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_csr.h        | 161 ++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h        |   7 +
 drivers/gpu/drm/i915/intel_runtime_pm.c | 210 +++++++++++++++++++++++-
 9 files changed, 759 insertions(+), 4 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_csr.c
 create mode 100644 drivers/gpu/drm/i915/intel_csr.h

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

* [PATCH v2 1/8] drm/i915/skl: Add support to load SKL CSR firmware.
  2015-04-02 15:21   ` [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware Imre Deak
@ 2015-04-10 15:11     ` Animesh Manna
  2015-04-13 10:24       ` [PATCH v3 " Animesh Manna
  0 siblings, 1 reply; 46+ messages in thread
From: Animesh Manna @ 2015-04-10 15:11 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)

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  | 13 ++++++++++++-
 drivers/gpu/drm/i915/i915_drv.c  | 20 ++++++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h  | 17 +++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |  5 +++++
 5 files changed, 56 insertions(+), 2 deletions(-)

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..6247d05 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,10 +862,16 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
 	intel_uncore_init(dev);
 
-	ret = i915_gem_gtt_init(dev);
+	/* Load CSR Firmware for SKL */
+	intel_csr_ucode_init(dev);
+
 	if (ret)
 		goto out_regs;
 
+	ret = i915_gem_gtt_init(dev);
+	if (ret)
+		goto out_freecsr;
+
 	/* WARNING: Apparently we must kick fbdev drivers before vgacon,
 	 * otherwise the vga fbdev driver falls over. */
 	ret = i915_kick_out_firmware_fb(dev_priv);
@@ -1033,6 +1040,8 @@ out_mtrrfree:
 	io_mapping_free(dev_priv->gtt.mappable);
 out_gtt:
 	i915_global_gtt_cleanup(dev);
+out_freecsr:
+	intel_csr_ucode_fini(dev);
 out_regs:
 	intel_uncore_fini(dev);
 	pci_iounmap(dev->pdev, dev_priv->regs);
@@ -1113,6 +1122,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 dcdd17a..d0325ef 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_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index efa53d5..9f4a6f6 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1056,6 +1056,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] 46+ messages in thread

* [PATCH v2 3/8] drm/i915/skl: Add DC5 Trigger Sequence.
  2015-04-02 19:33     ` Imre Deak
@ 2015-04-10 15:11       ` Animesh Manna
  2015-04-13 10:26         ` [PATCH v3 " Animesh Manna
  0 siblings, 1 reply; 46+ messages in thread
From: Animesh Manna @ 2015-04-10 15:11 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)

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_drv.h        |  2 ++
 drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +++++++++++++++++++++++++++++
 3 files changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d0325ef..841e0bb 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_states {
+	FW_LOADED = 0,
+	FW_LOADING,
+	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_states states;
 };
 
 #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9f4a6f6..5280fbe 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1058,6 +1058,8 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
 
 /* intel_csr.c */
 void intel_csr_ucode_init(struct drm_device *dev);
+bool intel_csr_load_status_get(struct drm_i915_private *dev_priv);
+void intel_csr_load_status_set(struct drm_i915_private *dev_priv, bool val);
 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 bc6cee9..0750191 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 &&			\
@@ -369,6 +371,7 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
 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;
@@ -408,6 +411,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);
 		}
 
@@ -424,6 +434,25 @@ 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) {
+				if (dev_priv->csr.states <= FW_LOADING) {
+					/*
+					* TODO: wait for a completion event or
+					* similar here instead of busy
+					* waiting using wait_for function.
+					*/
+					if (wait_for(
+						intel_csr_load_status_get(
+							dev_priv), 1000))
+						DRM_ERROR("Timed out waiting for CSR to be loaded!");
+					else
+						gen9_enable_dc5(dev_priv);
+				} else {
+					DRM_ERROR("Cannot enable DC5 as CSR failed to load!");
+				}
+			}
 		}
 	}
 
-- 
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] 46+ messages in thread

* [PATCH v2 4/8] drm/i915/skl: Assert the requirements to enter or exit DC5.
  2015-04-02 20:17     ` Imre Deak
@ 2015-04-10 15:11       ` Animesh Manna
  2015-04-13 12:46         ` Imre Deak
  0 siblings, 1 reply; 46+ messages in thread
From: Animesh Manna @ 2015-04-10 15:11 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 chnages 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_runtime_pm.c | 61 ++++++++++++++++++++++++++++++---
 1 file changed, 56 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 0750191..db25eb7 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -31,6 +31,7 @@
 
 #include "i915_drv.h"
 #include "intel_drv.h"
+#include "intel_csr.h"
 
 /**
  * DOC: runtime pm
@@ -64,6 +65,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 +339,48 @@ static void gen9_set_dc_state_debugmask_memory_up(
 	}
 }
 
-static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
+static void assert_csr_loaded(struct drm_i915_private *dev_priv)
+{
+	WARN(!dev_priv->csr.states, "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");
+}
+
+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 +395,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");
 
@@ -1324,7 +1363,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;
@@ -1338,6 +1377,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] 46+ messages in thread

* [PATCH v2 6/8] drm/i915/skl: Add DC6 Trigger sequence.
  2015-04-02 20:42     ` Imre Deak
@ 2015-04-10 15:11       ` Animesh Manna
  2015-04-13 12:50         ` Imre Deak
  0 siblings, 1 reply; 46+ messages in thread
From: Animesh Manna @ 2015-04-10 15:11 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 | 40 ++++++++++++++++++++++-----------
 2 files changed, 57 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index acd0e2b..7a1123c 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, false);
+
+	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 ea95df7..6cf54c1 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -50,7 +50,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;							\
@@ -438,8 +439,6 @@ static void skl_disable_dc6(struct drm_i915_private *dev_priv)
 	val &= ~DC_STATE_EN_UPTO_DC6;
 	I915_WRITE(DC_STATE_EN, val);
 	POSTING_READ(DC_STATE_EN);
-
-	intel_prepare_ddi(dev);
 }
 
 static void skl_set_power_well(struct drm_i915_private *dev_priv,
@@ -489,9 +488,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);
 		}
 
@@ -509,22 +520,25 @@ 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) {
 				if (dev_priv->csr.states <= FW_LOADING) {
 					/*
-					* TODO: wait for a completion event or
-					* similar here instead of busy
-					* waiting using wait_for function.
-					*/
+					 * TODO: wait for a completion event or similar here instead of busy
+					 * waiting using wait_for function.
+					 */
 					if (wait_for(
 						intel_csr_load_status_get(
 							dev_priv), 1000))
 						DRM_ERROR("Timed out waiting for CSR to be loaded!");
 					else
-						gen9_enable_dc5(dev_priv);
+						if (SKL_ENABLE_DC6(dev))
+							skl_enable_dc6(dev_priv);
+						else
+							gen9_enable_dc5(dev_priv);
 				} else {
-					DRM_ERROR("Cannot enable DC5 as CSR failed to load!");
+					DRM_ERROR("Cannot enable %s as CSR failed to load!",
+						SKL_ENABLE_DC6(dev) ? "DC6" : "DC5");
 				}
 			}
 		}
-- 
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] 46+ messages in thread

* [PATCH v2 7/8] drm/i915/skl: Assert the requirements to enter or exit DC6.
  2015-04-02 20:49     ` Imre Deak
@ 2015-04-10 15:12       ` Animesh Manna
  0 siblings, 0 replies; 46+ messages in thread
From: Animesh Manna @ 2015-04-10 15:12 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 6cf54c1..3f50202 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -371,6 +371,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,
@@ -408,12 +414,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");
 
@@ -428,10 +461,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] 46+ messages in thread

* [PATCH v3 1/8] drm/i915/skl: Add support to load SKL CSR firmware
  2015-04-10 15:11     ` [PATCH v2 " Animesh Manna
@ 2015-04-13 10:24       ` Animesh Manna
  2015-04-13 11:03         ` Imre Deak
  2015-04-13 16:34         ` Damien Lespiau
  0 siblings, 2 replies; 46+ messages in thread
From: Animesh Manna @ 2015-04-13 10:24 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. (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 | 234 +++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_csr.h | 164 +++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |   5 +
 7 files changed, 451 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_csr.c
 create mode 100644 drivers/gpu/drm/i915/intel_csr.h

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..ab9b16b
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -0,0 +1,234 @@
+/*
+ * 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"
+#include "intel_csr.h"
+
+static 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 is dwords, converting it to bytes and nearest 8 multiple. */
+	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_csr.h b/drivers/gpu/drm/i915/intel_csr.h
new file mode 100644
index 0000000..c2a5a53
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_csr.h
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _INTEL_CSR_H_
+#define _INTEL_CSR_H_
+
+#define I915_CSR_SKL "i915/dmc_gen9.bin"
+
+MODULE_FIRMWARE(I915_CSR_SKL);
+
+/*
+* SKL CSR registers for DC5 and DC6
+*/
+#define CSR_PROGRAM_BASE		0x80000
+#define CSR_HEADER_OFFSET		128
+#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;
+} __packed;
+
+
+#endif /* _INTEL_CSR_H_ */
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] 46+ messages in thread

* [PATCH v3 3/8] drm/i915/skl: Add DC5 Trigger Sequence
  2015-04-10 15:11       ` [PATCH v2 " Animesh Manna
@ 2015-04-13 10:26         ` Animesh Manna
  2015-04-13 11:33           ` Imre Deak
                             ` (2 more replies)
  0 siblings, 3 replies; 46+ messages in thread
From: Animesh Manna @ 2015-04-13 10:26 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)

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        | 51 +++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_drv.h        |  2 ++
 drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +++++++++++++++++++
 4 files changed, 87 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 90e47a9..8d6deaa 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_states {
+	FW_LOADED = 0,
+	FW_LOADING,
+	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_states states;
 };
 
 #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 ab9b16b..6d08a41 100644
--- a/drivers/gpu/drm/i915/intel_csr.c
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -49,6 +49,25 @@ static char intel_get_substepping(struct drm_device *dev)
 	else
 		return -ENODATA;
 }
+
+bool intel_csr_load_status_get(struct drm_i915_private *dev_priv)
+{
+	bool val = false;
+
+	mutex_lock(&dev_priv->csr_lock);
+	val = dev_priv->csr.states;
+	mutex_unlock(&dev_priv->csr_lock);
+
+	return val;
+}
+
+void intel_csr_load_status_set(struct drm_i915_private *dev_priv, bool val)
+{
+	mutex_lock(&dev_priv->csr_lock);
+	dev_priv->csr.states = val;
+	mutex_unlock(&dev_priv->csr_lock);
+}
+
 void intel_csr_load_program(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -71,6 +90,8 @@ void intel_csr_load_program(struct drm_device *dev)
 		I915_WRITE(dev_priv->csr.mmioaddr[i],
 			dev_priv->csr.mmiodata[i]);
 	}
+
+	intel_csr_load_status_set(dev_priv, FW_LOADED);
 	mutex_unlock(&dev_priv->csr_lock);
 }
 
@@ -90,11 +111,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;
 	}
 
@@ -104,6 +127,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);
@@ -115,6 +139,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);
@@ -135,6 +160,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;
@@ -144,6 +170,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);
@@ -152,6 +179,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;
@@ -160,6 +188,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];
@@ -170,6 +199,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;
@@ -177,6 +207,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;
 	}
 
@@ -194,6 +225,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);
 }
 
@@ -210,17 +246,27 @@ 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);
+
+	intel_csr_load_status_set(dev_priv, FW_LOADING);
+
 	/* 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)
@@ -230,5 +276,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..3fc2473 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1064,6 +1064,8 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
 
 /* intel_csr.c */
 void intel_csr_ucode_init(struct drm_device *dev);
+bool intel_csr_load_status_get(struct drm_i915_private *dev_priv);
+void intel_csr_load_status_set(struct drm_i915_private *dev_priv, bool val);
 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 bc6cee9..0750191 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 &&			\
@@ -369,6 +371,7 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
 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;
@@ -408,6 +411,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);
 		}
 
@@ -424,6 +434,25 @@ 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) {
+				if (dev_priv->csr.states <= FW_LOADING) {
+					/*
+					* TODO: wait for a completion event or
+					* similar here instead of busy
+					* waiting using wait_for function.
+					*/
+					if (wait_for(
+						intel_csr_load_status_get(
+							dev_priv), 1000))
+						DRM_ERROR("Timed out waiting for CSR to be loaded!");
+					else
+						gen9_enable_dc5(dev_priv);
+				} else {
+					DRM_ERROR("Cannot enable DC5 as CSR failed to load!");
+				}
+			}
 		}
 	}
 
-- 
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] 46+ messages in thread

* Re: [PATCH v3 1/8] drm/i915/skl: Add support to load SKL CSR firmware
  2015-04-13 10:24       ` [PATCH v3 " Animesh Manna
@ 2015-04-13 11:03         ` Imre Deak
  2015-04-13 13:07           ` Animesh Manna
  2015-04-13 16:34         ` Damien Lespiau
  1 sibling, 1 reply; 46+ messages in thread
From: Imre Deak @ 2015-04-13 11:03 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx

On ma, 2015-04-13 at 15:54 +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. (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 | 234 +++++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_csr.h | 164 +++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h |   5 +
>  7 files changed, 451 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/intel_csr.c
>  create mode 100644 drivers/gpu/drm/i915/intel_csr.h
> 
> 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..ab9b16b
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_csr.c
> @@ -0,0 +1,234 @@
> +/*
> + * 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"
> +#include "intel_csr.h"
> +
> +static struct stepping_info skl_stepping_info[] = {

Nitpick: this should be const.

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

Nitpick: at this point it's just
if (dev->pdev->revision < 9)
	return 'A' + dev->pdev->revision;

w/o the need for skl_stepping_info.

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

and this one is simply
return 0;

> +	else
> +		return -ENODATA;
> +}

Missing newline.

> +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 is dwords, converting it to bytes and nearest 8 multiple. */

The above comment is stale now.

> +	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_csr.h b/drivers/gpu/drm/i915/intel_csr.h
> new file mode 100644
> index 0000000..c2a5a53
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_csr.h
> @@ -0,0 +1,164 @@
> +/*
> + * 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.
> + *
> + */
> +
> +#ifndef _INTEL_CSR_H_
> +#define _INTEL_CSR_H_
> +
> +#define I915_CSR_SKL "i915/dmc_gen9.bin"
> +
> +MODULE_FIRMWARE(I915_CSR_SKL);
> +
> +/*
> +* SKL CSR registers for DC5 and DC6
> +*/
> +#define CSR_PROGRAM_BASE		0x80000
> +#define CSR_HEADER_OFFSET		128
> +#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;
> +} __packed;

stepping_info doesn't need to be packed.

What I meant is to add all these to intel_csr.c. I don't think there is
any reason for a new header file unless you need to share something
among multiple .c modules.

--Imre

> +
> +
> +#endif /* _INTEL_CSR_H_ */
> 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] 46+ messages in thread

* Re: [PATCH v3 3/8] drm/i915/skl: Add DC5 Trigger Sequence
  2015-04-13 10:26         ` [PATCH v3 " Animesh Manna
@ 2015-04-13 11:33           ` Imre Deak
  2015-04-13 17:41             ` Damien Lespiau
  2015-04-13 15:25           ` Damien Lespiau
  2015-04-13 17:49           ` Damien Lespiau
  2 siblings, 1 reply; 46+ messages in thread
From: Imre Deak @ 2015-04-13 11:33 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On ma, 2015-04-13 at 15:56 +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)
> 
> 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        | 51 +++++++++++++++++++++++++++++++--
>  drivers/gpu/drm/i915/intel_drv.h        |  2 ++
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +++++++++++++++++++
>  4 files changed, 87 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 90e47a9..8d6deaa 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_states {

Nitpick: just csr_state.

> +	FW_LOADED = 0,
> +	FW_LOADING,
> +	FW_FAILED
> +};

I'd rather have FW_LOADING = 0, as that's what the uninitialized state
really is. You could also rename it to FW_UNINITIALIZED accordingly.

> +
>  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_states states;
>  };
>  
>  #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 ab9b16b..6d08a41 100644
> --- a/drivers/gpu/drm/i915/intel_csr.c
> +++ b/drivers/gpu/drm/i915/intel_csr.c
> @@ -49,6 +49,25 @@ static char intel_get_substepping(struct drm_device *dev)
>  	else
>  		return -ENODATA;
>  }
> +
> +bool intel_csr_load_status_get(struct drm_i915_private *dev_priv)
> +{
> +	bool val = false;
> +
> +	mutex_lock(&dev_priv->csr_lock);
> +	val = dev_priv->csr.states;
> +	mutex_unlock(&dev_priv->csr_lock);
> +
> +	return val;
> +}
> +
> +void intel_csr_load_status_set(struct drm_i915_private *dev_priv, bool val)
> +{
> +	mutex_lock(&dev_priv->csr_lock);
> +	dev_priv->csr.states = val;
> +	mutex_unlock(&dev_priv->csr_lock);
> +}
> +
>  void intel_csr_load_program(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -71,6 +90,8 @@ void intel_csr_load_program(struct drm_device *dev)
>  		I915_WRITE(dev_priv->csr.mmioaddr[i],
>  			dev_priv->csr.mmiodata[i]);
>  	}
> +
> +	intel_csr_load_status_set(dev_priv, FW_LOADED);
>  	mutex_unlock(&dev_priv->csr_lock);
>  }
>  
> @@ -90,11 +111,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;
>  	}
>  
> @@ -104,6 +127,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);
> @@ -115,6 +139,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);
> @@ -135,6 +160,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;
> @@ -144,6 +170,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);
> @@ -152,6 +179,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;
> @@ -160,6 +188,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];
> @@ -170,6 +199,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;
> @@ -177,6 +207,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;
>  	}
>  
> @@ -194,6 +225,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);
>  }
>  
> @@ -210,17 +246,27 @@ 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);
> +
> +	intel_csr_load_status_set(dev_priv, FW_LOADING);

With the above change this wouldn't be needed.

> +
>  	/* 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)
> @@ -230,5 +276,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..3fc2473 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1064,6 +1064,8 @@ unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
>  
>  /* intel_csr.c */
>  void intel_csr_ucode_init(struct drm_device *dev);
> +bool intel_csr_load_status_get(struct drm_i915_private *dev_priv);
> +void intel_csr_load_status_set(struct drm_i915_private *dev_priv, bool val);
>  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 bc6cee9..0750191 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 &&			\
> @@ -369,6 +371,7 @@ static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
>  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;
> @@ -408,6 +411,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);
>  		}
>  
> @@ -424,6 +434,25 @@ 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) {
> +				if (dev_priv->csr.states <= FW_LOADING) {
> +					/*
> +					* TODO: wait for a completion event or
> +					* similar here instead of busy
> +					* waiting using wait_for function.
> +					*/
> +					if (wait_for(
> +						intel_csr_load_status_get(
> +							dev_priv), 1000))
> +						DRM_ERROR("Timed out waiting for CSR to be loaded!");

This waits until the state is set to FW_LOADING or FW_FAILED, whereas it
should wait until it's FW_LOADED. I think the above block becomes
clearer by returning the state from the helper:

if (GEN9_ENABLE_DC5(dev) && power_well->data == SKL_DISP_PW_2) {
	enum csr_state state;

	wait_for((state = intel_csr_state(dev_priv)) != FW_UNINITIALIZED, 1000);
	if (state != FW_LOADED)
		DRM_ERROR("CSR firmware not ready (%d)\n", state);
	else
		gen9_enable_dc5(dev_priv);
}

> +					else
> +						gen9_enable_dc5(dev_priv);
> +				} else {
> +					DRM_ERROR("Cannot enable DC5 as CSR failed to load!");
> +				}
> +			}
>  		}
>  	}
>  


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

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

* Re: [PATCH v3 1/8] drm/i915/skl: Add support to load SKL CSR firmware
  2015-04-13 13:07           ` Animesh Manna
@ 2015-04-13 12:37             ` Imre Deak
  0 siblings, 0 replies; 46+ messages in thread
From: Imre Deak @ 2015-04-13 12:37 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx

On ma, 2015-04-13 at 18:37 +0530, Animesh Manna wrote:
> 
> On 04/13/2015 04:33 PM, Imre Deak wrote:
> > On ma, 2015-04-13 at 15:54 +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. (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 | 234 +++++++++++++++++++++++++++++++++++++++
> >>   drivers/gpu/drm/i915/intel_csr.h | 164 +++++++++++++++++++++++++++
> >>   drivers/gpu/drm/i915/intel_drv.h |   5 +
> >>   7 files changed, 451 insertions(+), 3 deletions(-)
> >>   create mode 100644 drivers/gpu/drm/i915/intel_csr.c
> >>   create mode 100644 drivers/gpu/drm/i915/intel_csr.h
> >>
> >> 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..ab9b16b
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/i915/intel_csr.c
> >> @@ -0,0 +1,234 @@
> >> +/*
> >> + * 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"
> >> +#include "intel_csr.h"
> >> +
> >> +static struct stepping_info skl_stepping_info[] = {
> > Nitpick: this should be const.
> >
> >> +		{'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;
> > Nitpick: at this point it's just
> > if (dev->pdev->revision < 9)
> > 	return 'A' + dev->pdev->revision;
> >
> > w/o the need for skl_stepping_info.
>
> If we have different firmwares for different substepping for example
> A0,A1,A3 then stepping will be same but substepping will be different
> and I assume revision_id also will be different. And if we want to put
> some logic like ('A' + dev->pdev->revision) then we can do it but
> should be based on bspec, Why I am telling because if later we get some
> table and not able to derive a common logic then again may need this
> kind of lookup table.
>
> And using lookuo table comes with advantage
> - to extend support for future platform only have to add new structure or
>   change existing structure to incorporate any future changes in stepping
>   info which got from bspec. - time complexity will be less.
>
> Yes agree space might be an issue. Suggest me trade off between time and
> space.

It would be just simpler in the above way, it's not a space issue. I
think once we have platforms with substeppings other than 0, we will
anyway have to change the above struct stepping_info and the logic to
look up the proper entry in it. But the above works too, so I'm ok if
you keep it as-is for now. Just make the struct const please.

> >> +	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;
> > and this one is simply
> > return 0;
>
> For now all values are 0 for skl, but implementation done thinking of
> supporting future changes. We may have multiple firmware for different
> substepping.

Ok, let's keep it as-is.

> >> +	else
> >> +		return -ENODATA;
> >> +}
> > Missing newline.
> >
> >> +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 is dwords, converting it to bytes and nearest 8 multiple. */
> > The above comment is stale now.
> 
> Agree.
> 
> >
> >> +	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_csr.h b/drivers/gpu/drm/i915/intel_csr.h
> >> new file mode 100644
> >> index 0000000..c2a5a53
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/i915/intel_csr.h
> >> @@ -0,0 +1,164 @@
> >> +/*
> >> + * 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.
> >> + *
> >> + */
> >> +
> >> +#ifndef _INTEL_CSR_H_
> >> +#define _INTEL_CSR_H_
> >> +
> >> +#define I915_CSR_SKL "i915/dmc_gen9.bin"
> >> +
> >> +MODULE_FIRMWARE(I915_CSR_SKL);
> >> +
> >> +/*
> >> +* SKL CSR registers for DC5 and DC6
> >> +*/
> >> +#define CSR_PROGRAM_BASE		0x80000
> >> +#define CSR_HEADER_OFFSET		128
> >> +#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;
> >> +} __packed;
> > stepping_info doesn't need to be packed.
> 
> To avoid structure padding used __packed which will save some memory.

No, the reason for __packed above is simply correctness for binary
interfaces like what we have with the DMC firmware. For anything else we
can trust the compiler to do the right thing wrt. to alignment/padding.

> > What I meant is to add all these to intel_csr.c. I don't think
> > there is any reason for a new header file unless you need to share
> > somethinh among multiple .c modules.
>
> intel_runtime_pm.c is using few macro which is defined in this header
> file in later patches. Then we can move all macro definition to
> i915_drv.h or else can put few macro in intel_csr.c and few in
> i915_drv.h. Give me your suggestion.

Yes, I missed assert_csr_loaded(). As this is really something internal
to the DMC firmware, I would just move assert_csr_loaded() to
intel_csr.c and export that from intel_drv.h.

--Imre

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

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

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

On pe, 2015-04-10 at 20:41 +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 chnages 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_runtime_pm.c | 61 ++++++++++++++++++++++++++++++---
>  1 file changed, 56 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 0750191..db25eb7 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -31,6 +31,7 @@
>  
>  #include "i915_drv.h"
>  #include "intel_drv.h"
> +#include "intel_csr.h"
>  
>  /**
>   * DOC: runtime pm
> @@ -64,6 +65,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 +339,48 @@ static void gen9_set_dc_state_debugmask_memory_up(
>  	}
>  }
>  
> -static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
> +static void assert_csr_loaded(struct drm_i915_private *dev_priv)
> +{
> +	WARN(!dev_priv->csr.states, "CSR is not loaded.\n");

This is now the wrong condition, should be something like
intel_csr_state(dev_priv) != FW_LOADED.

> +	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");
> +}
> +
> +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 +395,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");
>  
> @@ -1324,7 +1363,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;
> @@ -1338,6 +1377,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] 46+ messages in thread

* Re: [PATCH v2 6/8] drm/i915/skl: Add DC6 Trigger sequence.
  2015-04-10 15:11       ` [PATCH v2 " Animesh Manna
@ 2015-04-13 12:50         ` Imre Deak
  0 siblings, 0 replies; 46+ messages in thread
From: Imre Deak @ 2015-04-13 12:50 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On pe, 2015-04-10 at 20:41 +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 | 40 ++++++++++++++++++++++-----------
>  2 files changed, 57 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index acd0e2b..7a1123c 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, false);

This sets the wrong state now, should be something like
intel_csr_state_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 ea95df7..6cf54c1 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -50,7 +50,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;							\
> @@ -438,8 +439,6 @@ static void skl_disable_dc6(struct drm_i915_private *dev_priv)
>  	val &= ~DC_STATE_EN_UPTO_DC6;
>  	I915_WRITE(DC_STATE_EN, val);
>  	POSTING_READ(DC_STATE_EN);
> -
> -	intel_prepare_ddi(dev);
>  }
>  
>  static void skl_set_power_well(struct drm_i915_private *dev_priv,
> @@ -489,9 +488,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);
>  		}
>  
> @@ -509,22 +520,25 @@ 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) {
>  				if (dev_priv->csr.states <= FW_LOADING) {
>  					/*
> -					* TODO: wait for a completion event or
> -					* similar here instead of busy
> -					* waiting using wait_for function.
> -					*/
> +					 * TODO: wait for a completion event or similar here instead of busy
> +					 * waiting using wait_for function.
> +					 */
>  					if (wait_for(
>  						intel_csr_load_status_get(
>  							dev_priv), 1000))
>  						DRM_ERROR("Timed out waiting for CSR to be loaded!");
>  					else
> -						gen9_enable_dc5(dev_priv);
> +						if (SKL_ENABLE_DC6(dev))
> +							skl_enable_dc6(dev_priv);
> +						else
> +							gen9_enable_dc5(dev_priv);
>  				} else {
> -					DRM_ERROR("Cannot enable DC5 as CSR failed to load!");
> +					DRM_ERROR("Cannot enable %s as CSR failed to load!",
> +						SKL_ENABLE_DC6(dev) ? "DC6" : "DC5");
>  				}
>  			}
>  		}


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

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

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



On 04/13/2015 04:33 PM, Imre Deak wrote:
> On ma, 2015-04-13 at 15:54 +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. (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 | 234 +++++++++++++++++++++++++++++++++++++++
>>   drivers/gpu/drm/i915/intel_csr.h | 164 +++++++++++++++++++++++++++
>>   drivers/gpu/drm/i915/intel_drv.h |   5 +
>>   7 files changed, 451 insertions(+), 3 deletions(-)
>>   create mode 100644 drivers/gpu/drm/i915/intel_csr.c
>>   create mode 100644 drivers/gpu/drm/i915/intel_csr.h
>>
>> 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..ab9b16b
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/intel_csr.c
>> @@ -0,0 +1,234 @@
>> +/*
>> + * 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"
>> +#include "intel_csr.h"
>> +
>> +static struct stepping_info skl_stepping_info[] = {
> Nitpick: this should be const.
>
>> +		{'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;
> Nitpick: at this point it's just
> if (dev->pdev->revision < 9)
> 	return 'A' + dev->pdev->revision;
>
> w/o the need for skl_stepping_info.

If we have different firmwares for different substepping for example A0,A1,A3 then stepping will
be same but substepping will be different and I assume revision_id also will be different. And
if we want to put some logic like ('A' + dev->pdev->revision) then we can do it but should be
based on bspec, Why I am telling because if later we get some table and not able to derive
a common logic then again may need this kind of lookup table.

And using lookuo table comes with advantage
- to extend support for future platform only have to add new structure or change existing
structure to incorporate any future changes in stepping info which got from bspec.
- time complexity will be less.

Yes agree space might be an issue. Suggest me trade off between time and space.

>    
>
>> +	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;
> and this one is simply
> return 0;

For now all values are 0 for skl, but implementation done thinking of supporting future changes.
We may have multiple firmware for different substepping.

>> +	else
>> +		return -ENODATA;
>> +}
> Missing newline.
>
>> +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 is dwords, converting it to bytes and nearest 8 multiple. */
> The above comment is stale now.

Agree.

>
>> +	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_csr.h b/drivers/gpu/drm/i915/intel_csr.h
>> new file mode 100644
>> index 0000000..c2a5a53
>> --- /dev/null
>> +++ b/drivers/gpu/drm/i915/intel_csr.h
>> @@ -0,0 +1,164 @@
>> +/*
>> + * 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.
>> + *
>> + */
>> +
>> +#ifndef _INTEL_CSR_H_
>> +#define _INTEL_CSR_H_
>> +
>> +#define I915_CSR_SKL "i915/dmc_gen9.bin"
>> +
>> +MODULE_FIRMWARE(I915_CSR_SKL);
>> +
>> +/*
>> +* SKL CSR registers for DC5 and DC6
>> +*/
>> +#define CSR_PROGRAM_BASE		0x80000
>> +#define CSR_HEADER_OFFSET		128
>> +#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;
>> +} __packed;
> stepping_info doesn't need to be packed.

To avoid structure padding used __packed which will save some memory.
  

>
> What I meant is to add all these to intel_csr.c. I don't think there is
> any reason for a new header file unless you need to share something
> among multiple .c modules.
>
> --Imre

intel_runtime_pm.c is using few macro which is defined in this header file in later patches.
Then we can move all macro definition to i915_drv.h or else can put few macro in intel_csr.c
and few in i915_drv.h. Give me your suggestion.

Regards,
Animesh

>
>> +
>> +
>> +#endif /* _INTEL_CSR_H_ */
>> 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] 46+ messages in thread

* Re: [PATCH 2/8] drm/i915/skl: Implement enable/disable for Display C5 sttate.
  2015-04-02 15:58     ` Imre Deak
@ 2015-04-13 13:17       ` Damien Lespiau
  2015-04-13 13:51         ` Imre Deak
  0 siblings, 1 reply; 46+ messages in thread
From: Damien Lespiau @ 2015-04-13 13:17 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Thu, Apr 02, 2015 at 06:58:22PM +0300, Imre Deak wrote:
> On ke, 2015-04-01 at 16: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.
> 
> Reviewed-by: Imre Deak <imre.deak@intel.com>

For the record, this patch generates compilation warnings when applied
on its own:

drivers/gpu/drm/i915/intel_runtime_pm.c:368:13: warning: ‘gen9_enable_dc5’ defined but not used [-Wunused-function]
 static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
             ^
drivers/gpu/drm/i915/intel_runtime_pm.c:386:13: warning: ‘gen9_disable_dc5’ defined but not used [-Wunused-function]
 static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
             ^

Generally speaking, in a series, each step should compile without warning and
result in a working driver (for bisectability).

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

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

* Re: [PATCH 2/8] drm/i915/skl: Implement enable/disable for Display C5 sttate.
  2015-04-13 13:17       ` Damien Lespiau
@ 2015-04-13 13:51         ` Imre Deak
  2015-04-14 11:50           ` Daniel Vetter
  0 siblings, 1 reply; 46+ messages in thread
From: Imre Deak @ 2015-04-13 13:51 UTC (permalink / raw)
  To: Damien Lespiau; +Cc: intel-gfx

On ma, 2015-04-13 at 14:17 +0100, Damien Lespiau wrote:
> On Thu, Apr 02, 2015 at 06:58:22PM +0300, Imre Deak wrote:
> > On ke, 2015-04-01 at 16: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.
> > 
> > Reviewed-by: Imre Deak <imre.deak@intel.com>
> 
> For the record, this patch generates compilation warnings when applied
> on its own:
> 
> drivers/gpu/drm/i915/intel_runtime_pm.c:368:13: warning: ‘gen9_enable_dc5’ defined but not used [-Wunused-function]
>  static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
>              ^
> drivers/gpu/drm/i915/intel_runtime_pm.c:386:13: warning: ‘gen9_disable_dc5’ defined but not used [-Wunused-function]
>  static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
>              ^
> 
> Generally speaking, in a series, each step should compile without warning and
> result in a working driver (for bisectability).

Yes, agreed. Splitting the changes into patches could've been done in
better a way. I also commented on a related topic of adding something in
the patchset and removing it later. We'll try to pay more attention to
this in the future.

Animesh, if you resend this patchset anyway I think you could switch the
order of 2/8 and 3/8 and add the calls to the above functions in this
patch to get rid of the warnings. Also please make sure that things
compile without a warning after each patch as Damien suggested.

--Imre


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

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

* Re: [PATCH v3 3/8] drm/i915/skl: Add DC5 Trigger Sequence
  2015-04-13 10:26         ` [PATCH v3 " Animesh Manna
  2015-04-13 11:33           ` Imre Deak
@ 2015-04-13 15:25           ` Damien Lespiau
  2015-04-13 17:49           ` Damien Lespiau
  2 siblings, 0 replies; 46+ messages in thread
From: Damien Lespiau @ 2015-04-13 15:25 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On Mon, Apr 13, 2015 at 03:56:23PM +0530, Animesh Manna wrote:
> @@ -71,6 +90,8 @@ void intel_csr_load_program(struct drm_device *dev)
>  		I915_WRITE(dev_priv->csr.mmioaddr[i],
>  			dev_priv->csr.mmiodata[i]);
>  	}
> +
> +	intel_csr_load_status_set(dev_priv, FW_LOADED);
>  	mutex_unlock(&dev_priv->csr_lock);
>  }

This doesn't look correct: you're already inside a section with csr_lock
taken, intel_csr_load_status_set() tries to take csr_lock and mutexes
aren't recursive.

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

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

* Re: [PATCH v3 1/8] drm/i915/skl: Add support to load SKL CSR firmware
  2015-04-13 10:24       ` [PATCH v3 " Animesh Manna
  2015-04-13 11:03         ` Imre Deak
@ 2015-04-13 16:34         ` Damien Lespiau
  2015-04-13 16:52           ` Imre Deak
       [not found]           ` <20804_1428943986_552BF472_20804_13643_1_1428943974.12269.9.camel@ideak-mobl>
  1 sibling, 2 replies; 46+ messages in thread
From: Damien Lespiau @ 2015-04-13 16:34 UTC (permalink / raw)
  To: Animesh Manna; +Cc: intel-gfx, jesse.barnes

On Mon, Apr 13, 2015 at 03:54:02PM +0530, Animesh Manna wrote:
> diff --git a/drivers/gpu/drm/i915/intel_csr.h b/drivers/gpu/drm/i915/intel_csr.h
> new file mode 100644
> index 0000000..c2a5a53
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/intel_csr.h
> +

[...]

> +#define I915_CSR_SKL "i915/dmc_gen9.bin"

I'm guessing the BXT DMC firwmare will be different from SKL's? Remember
that one of the requirements is to be able to have the same OS image
boot on both SKL and BXT. That means the firmware names have to be
different for SKL and BXT. We probably should have skl in the name here.

Also, we need to be able to be able to support "Interface" versions. Ie.
if the firmware interface changes in such a way a different loading code
is needed, we need to be able to have both firmware on the disk so both
an old kernel and a new kernel can work with the same user space.

Right now, the naming scheme of the firmware does have a version on it,
hopefully that's this "Interface" version.

Thoughts?

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

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

* Re: [PATCH v3 1/8] drm/i915/skl: Add support to load SKL CSR firmware
  2015-04-13 16:34         ` Damien Lespiau
@ 2015-04-13 16:52           ` Imre Deak
  2015-04-13 17:02             ` Damien Lespiau
       [not found]           ` <20804_1428943986_552BF472_20804_13643_1_1428943974.12269.9.camel@ideak-mobl>
  1 sibling, 1 reply; 46+ messages in thread
From: Imre Deak @ 2015-04-13 16:52 UTC (permalink / raw)
  To: Damien Lespiau; +Cc: jesse.barnes, intel-gfx

On Mon, 2015-04-13 at 17:34 +0100, Damien Lespiau wrote:
> On Mon, Apr 13, 2015 at 03:54:02PM +0530, Animesh Manna wrote:
> > diff --git a/drivers/gpu/drm/i915/intel_csr.h b/drivers/gpu/drm/i915/intel_csr.h
> > new file mode 100644
> > index 0000000..c2a5a53
> > --- /dev/null
> > +++ b/drivers/gpu/drm/i915/intel_csr.h
> > +
> 
> [...]
> 
> > +#define I915_CSR_SKL "i915/dmc_gen9.bin"
> 
> I'm guessing the BXT DMC firwmare will be different from SKL's? Remember
> that one of the requirements is to be able to have the same OS image
> boot on both SKL and BXT. That means the firmware names have to be
> different for SKL and BXT. We probably should have skl in the name here.
> 
> Also, we need to be able to be able to support "Interface" versions. Ie.
> if the firmware interface changes in such a way a different loading code
> is needed, we need to be able to have both firmware on the disk so both
> an old kernel and a new kernel can work with the same user space.
> 
> Right now, the naming scheme of the firmware does have a version on it,
> hopefully that's this "Interface" version.
>
> Thoughts?

Yes, the above file name looks incorrect. "dmc_gen9.bin" was the name
for the firmware image with the old layout. This patchset adds support
for the new firmware layout starting from ver 1, while the old layout
doesn't need to be supported. In an earlier version of this patch the
filename was changed to "i915/skl_dmc_ver1.bin" not sure why that change
got dropped. I think we could just use this latter name.

--Imre

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

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

* Re: [PATCH v3 1/8] drm/i915/skl: Add support to load SKL CSR firmware
  2015-04-13 16:52           ` Imre Deak
@ 2015-04-13 17:02             ` Damien Lespiau
  2015-04-13 17:15               ` Imre Deak
  0 siblings, 1 reply; 46+ messages in thread
From: Damien Lespiau @ 2015-04-13 17:02 UTC (permalink / raw)
  To: Imre Deak; +Cc: jesse.barnes, intel-gfx

On Mon, Apr 13, 2015 at 07:52:54PM +0300, Imre Deak wrote:
> On Mon, 2015-04-13 at 17:34 +0100, Damien Lespiau wrote:
> > On Mon, Apr 13, 2015 at 03:54:02PM +0530, Animesh Manna wrote:
> > > diff --git a/drivers/gpu/drm/i915/intel_csr.h b/drivers/gpu/drm/i915/intel_csr.h
> > > new file mode 100644
> > > index 0000000..c2a5a53
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/i915/intel_csr.h
> > > +
> > 
> > [...]
> > 
> > > +#define I915_CSR_SKL "i915/dmc_gen9.bin"
> > 
> > I'm guessing the BXT DMC firwmare will be different from SKL's? Remember
> > that one of the requirements is to be able to have the same OS image
> > boot on both SKL and BXT. That means the firmware names have to be
> > different for SKL and BXT. We probably should have skl in the name here.
> > 
> > Also, we need to be able to be able to support "Interface" versions. Ie.
> > if the firmware interface changes in such a way a different loading code
> > is needed, we need to be able to have both firmware on the disk so both
> > an old kernel and a new kernel can work with the same user space.
> > 
> > Right now, the naming scheme of the firmware does have a version on it,
> > hopefully that's this "Interface" version.
> >
> > Thoughts?
> 
> Yes, the above file name looks incorrect. "dmc_gen9.bin" was the name
> for the firmware image with the old layout. This patchset adds support
> for the new firmware layout starting from ver 1, while the old layout
> doesn't need to be supported. In an earlier version of this patch the
> filename was changed to "i915/skl_dmc_ver1.bin" not sure why that change
> got dropped. I think we could just use this latter name.

First public firmware is already v4 [1], no idea is the version bumps
are actual API/interface changes.

-- 
Damien

[1] https://01.org/linuxgraphics/downloads/2015/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH v3 1/8] drm/i915/skl: Add support to load SKL CSR firmware
  2015-04-13 17:02             ` Damien Lespiau
@ 2015-04-13 17:15               ` Imre Deak
  2015-04-13 17:22                 ` Damien Lespiau
  0 siblings, 1 reply; 46+ messages in thread
From: Imre Deak @ 2015-04-13 17:15 UTC (permalink / raw)
  To: Damien Lespiau; +Cc: jesse.barnes, intel-gfx

On Mon, 2015-04-13 at 18:02 +0100, Damien Lespiau wrote:
> On Mon, Apr 13, 2015 at 07:52:54PM +0300, Imre Deak wrote:
> > On Mon, 2015-04-13 at 17:34 +0100, Damien Lespiau wrote:
> > > On Mon, Apr 13, 2015 at 03:54:02PM +0530, Animesh Manna wrote:
> > > > diff --git a/drivers/gpu/drm/i915/intel_csr.h b/drivers/gpu/drm/i915/intel_csr.h
> > > > new file mode 100644
> > > > index 0000000..c2a5a53
> > > > --- /dev/null
> > > > +++ b/drivers/gpu/drm/i915/intel_csr.h
> > > > +
> > > 
> > > [...]
> > > 
> > > > +#define I915_CSR_SKL "i915/dmc_gen9.bin"
> > > 
> > > I'm guessing the BXT DMC firwmare will be different from SKL's? Remember
> > > that one of the requirements is to be able to have the same OS image
> > > boot on both SKL and BXT. That means the firmware names have to be
> > > different for SKL and BXT. We probably should have skl in the name here.
> > > 
> > > Also, we need to be able to be able to support "Interface" versions. Ie.
> > > if the firmware interface changes in such a way a different loading code
> > > is needed, we need to be able to have both firmware on the disk so both
> > > an old kernel and a new kernel can work with the same user space.
> > > 
> > > Right now, the naming scheme of the firmware does have a version on it,
> > > hopefully that's this "Interface" version.
> > >
> > > Thoughts?
> > 
> > Yes, the above file name looks incorrect. "dmc_gen9.bin" was the name
> > for the firmware image with the old layout. This patchset adds support
> > for the new firmware layout starting from ver 1, while the old layout
> > doesn't need to be supported. In an earlier version of this patch the
> > filename was changed to "i915/skl_dmc_ver1.bin" not sure why that change
> > got dropped. I think we could just use this latter name.
> 
> First public firmware is already v4 [1], no idea is the version bumps
> are actual API/interface changes.

Ok, I haven't seen that. One question is if we need to support multiple
interface versions or just the latest one. I would say only the latest
one (for each platform) and so I915_CSR_SKL should be this latest
firmware image filename, in this case i915/skl_dmc_ver4.bin.

--Imre

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

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

* Re: [PATCH v3 1/8] drm/i915/skl: Add support to load SKL CSR firmware
  2015-04-13 17:15               ` Imre Deak
@ 2015-04-13 17:22                 ` Damien Lespiau
  2015-04-14  9:16                   ` Animesh Manna
  0 siblings, 1 reply; 46+ messages in thread
From: Damien Lespiau @ 2015-04-13 17:22 UTC (permalink / raw)
  To: Imre Deak; +Cc: jesse.barnes, intel-gfx

On Mon, Apr 13, 2015 at 08:15:29PM +0300, Imre Deak wrote:
> Ok, I haven't seen that. One question is if we need to support multiple
> interface versions or just the latest one. I would say only the latest
> one (for each platform) and so I915_CSR_SKL should be this latest
> firmware image filename, in this case i915/skl_dmc_ver4.bin.

Yup, I think just supporting the latest one in the driver is what we
want. The filename versioning is there so different kernel versions,
supporting different interfaces, can all boot with the same userspace,
each kernel loading the appropriate firmware.

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

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

* Re: [PATCH v3 3/8] drm/i915/skl: Add DC5 Trigger Sequence
  2015-04-13 11:33           ` Imre Deak
@ 2015-04-13 17:41             ` Damien Lespiau
  0 siblings, 0 replies; 46+ messages in thread
From: Damien Lespiau @ 2015-04-13 17:41 UTC (permalink / raw)
  To: Imre Deak; +Cc: Suketu Shah, intel-gfx

On Mon, Apr 13, 2015 at 02:33:50PM +0300, Imre Deak wrote:
> > @@ -424,6 +434,25 @@ 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) {
> > +				if (dev_priv->csr.states <= FW_LOADING) {
> > +					/*
> > +					* TODO: wait for a completion event or
> > +					* similar here instead of busy
> > +					* waiting using wait_for function.
> > +					*/
> > +					if (wait_for(
> > +						intel_csr_load_status_get(
> > +							dev_priv), 1000))
> > +						DRM_ERROR("Timed out waiting for CSR to be loaded!");
> 
> This waits until the state is set to FW_LOADING or FW_FAILED, whereas it
> should wait until it's FW_LOADED. I think the above block becomes
> clearer by returning the state from the helper:
> 
> if (GEN9_ENABLE_DC5(dev) && power_well->data == SKL_DISP_PW_2) {
> 	enum csr_state state;
> 
> 	wait_for((state = intel_csr_state(dev_priv)) != FW_UNINITIALIZED, 1000);
> 	if (state != FW_LOADED)
> 		DRM_ERROR("CSR firmware not ready (%d)\n", state);
> 	else
> 		gen9_enable_dc5(dev_priv);
> }

Also, this level of indentation is becoming unmanageable. Maybe we
should move this code to skl_power_well_post_enable()?

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

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

* Re: [PATCH v3 3/8] drm/i915/skl: Add DC5 Trigger Sequence
  2015-04-13 10:26         ` [PATCH v3 " Animesh Manna
  2015-04-13 11:33           ` Imre Deak
  2015-04-13 15:25           ` Damien Lespiau
@ 2015-04-13 17:49           ` Damien Lespiau
  2 siblings, 0 replies; 46+ messages in thread
From: Damien Lespiau @ 2015-04-13 17:49 UTC (permalink / raw)
  To: Animesh Manna; +Cc: Suketu Shah, intel-gfx

On Mon, Apr 13, 2015 at 03:56:23PM +0530, Animesh Manna wrote:
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 90e47a9..8d6deaa 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_states {
> +	FW_LOADED = 0,
> +	FW_LOADING,
> +	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_states states;
>  };

Usually these kind of enum and variable are singular. enum csr_state and
state.

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

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

* ns2501 DVO - success at last
       [not found]           ` <20804_1428943986_552BF472_20804_13643_1_1428943974.12269.9.camel@ideak-mobl>
@ 2015-04-13 19:00             ` Thomas Richter
  2015-04-14 17:21               ` Daniel Vetter
  0 siblings, 1 reply; 46+ messages in thread
From: Thomas Richter @ 2015-04-13 19:00 UTC (permalink / raw)
  To: intel-gfx, Ville Syrjälä, Daniel Vetter

Hi Daniel, hi Ville,

some success at last. I couldn't stop myself playing with the NatSemi 
2501 DVO in my Fujitsu S6010 and I believe I finally got a hang on this 
chip. I believe I understand now most of the undocumented registers.

There are also a couple of additional features that are, apparently, not 
used by the video BIOS of the S6010, namely the chip has a ditherer on 
board - quite like the Intel Video Controller hub in the IBM R31.
Unfortunately, to enable the scaler, the bypass must be turned off, and 
hence, parameters for a 1:1 through-mapping of the scaler are required.

After quite some experimenting, I believe I found now the right settings 
to enable the scaler and configure it to pass the 1024x768 input to the 
output.

The chip is really a bit weird. It not only requires the scaling 
factors, but also the input timings, (sync width, front/back porch for 
both horizontal and vertical) and the output timing, and the 
configuration of its PLL to sample the incoming data. Currently, most of 
the data I obtained by "trail and error", at least for the 1024x768 mode 
in which the bios configures the DVO in bypass mode.

It turned out we forgot to configure a couple of registers (and some 
others are pretty much blank).

Thus, my question at this time is whether there is any interface how to 
get the precise timing of the loaded video mode from the i915 module 
directly instead of second-guessing the parameters, i.e. dimensions of 
the frame, porch sizes, size of the sync pulses, pixel clock and so on.

Other than that, I'll try to clean up the code I have to so far in the 
next days and release it.

Greetings,
	Thomas

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

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

* Re: [PATCH v3 1/8] drm/i915/skl: Add support to load SKL CSR firmware
  2015-04-13 17:22                 ` Damien Lespiau
@ 2015-04-14  9:16                   ` Animesh Manna
  2015-04-14 10:07                     ` Damien Lespiau
  0 siblings, 1 reply; 46+ messages in thread
From: Animesh Manna @ 2015-04-14  9:16 UTC (permalink / raw)
  To: Damien Lespiau, Imre Deak; +Cc: intel-gfx, jesse.barnes



On 04/13/2015 10:52 PM, Damien Lespiau wrote:
> On Mon, Apr 13, 2015 at 08:15:29PM +0300, Imre Deak wrote:
>> Ok, I haven't seen that. One question is if we need to support multiple
>> interface versions or just the latest one. I would say only the latest
>> one (for each platform) and so I915_CSR_SKL should be this latest
>> firmware image filename, in this case i915/skl_dmc_ver4.bin.
> Yup, I think just supporting the latest one in the driver is what we
> want. The filename versioning is there so different kernel versions,
> supporting different interfaces, can all boot with the same userspace,
> each kernel loading the appropriate firmware.
>
Can we have a symbolic link which can be hardcoded in intel_csr.c
and option will be given to user during installing the firmware
to create a symbolic link for the firmware wanted to load.
Want to avoid version number mentioned in firmware file name as it
getting change with latest fixes, bot not any API/inteface changes.
Agree as bxt and skl both are gen9 we can name as skl_dmc_gen9.bin
for now and discussion is going to finalize the name. Is it ok?


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

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

* Re: [PATCH v3 1/8] drm/i915/skl: Add support to load SKL CSR firmware
  2015-04-14  9:16                   ` Animesh Manna
@ 2015-04-14 10:07                     ` Damien Lespiau
  0 siblings, 0 replies; 46+ messages in thread
From: Damien Lespiau @ 2015-04-14 10:07 UTC (permalink / raw)
  To: Animesh Manna; +Cc: jesse.barnes, intel-gfx

On Tue, Apr 14, 2015 at 02:46:56PM +0530, Animesh Manna wrote:
> 
> 
> On 04/13/2015 10:52 PM, Damien Lespiau wrote:
> >On Mon, Apr 13, 2015 at 08:15:29PM +0300, Imre Deak wrote:
> >>Ok, I haven't seen that. One question is if we need to support multiple
> >>interface versions or just the latest one. I would say only the latest
> >>one (for each platform) and so I915_CSR_SKL should be this latest
> >>firmware image filename, in this case i915/skl_dmc_ver4.bin.
> >Yup, I think just supporting the latest one in the driver is what we
> >want. The filename versioning is there so different kernel versions,
> >supporting different interfaces, can all boot with the same userspace,
> >each kernel loading the appropriate firmware.
> >
> Can we have a symbolic link which can be hardcoded in intel_csr.c
> and option will be given to user during installing the firmware
> to create a symbolic link for the firmware wanted to load.
> Want to avoid version number mentioned in firmware file name as it
> getting change with latest fixes, bot not any API/inteface changes.
> Agree as bxt and skl both are gen9 we can name as skl_dmc_gen9.bin
> for now and discussion is going to finalize the name. Is it ok?

Why would we need a symlink? what would be its name? skl_dmc_gen9.bin
does not answer the requirement that we need to encode the API/interface
version in the filename. The firmware on 01.org skl_dmc_ver4.bin seems
to be what we want.

HTH,

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

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

* Re: [PATCH 2/8] drm/i915/skl: Implement enable/disable for Display C5 sttate.
  2015-04-13 13:51         ` Imre Deak
@ 2015-04-14 11:50           ` Daniel Vetter
  0 siblings, 0 replies; 46+ messages in thread
From: Daniel Vetter @ 2015-04-14 11:50 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Apr 13, 2015 at 04:51:37PM +0300, Imre Deak wrote:
> On ma, 2015-04-13 at 14:17 +0100, Damien Lespiau wrote:
> > On Thu, Apr 02, 2015 at 06:58:22PM +0300, Imre Deak wrote:
> > > On ke, 2015-04-01 at 16: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.
> > > 
> > > Reviewed-by: Imre Deak <imre.deak@intel.com>
> > 
> > For the record, this patch generates compilation warnings when applied
> > on its own:
> > 
> > drivers/gpu/drm/i915/intel_runtime_pm.c:368:13: warning: ‘gen9_enable_dc5’ defined but not used [-Wunused-function]
> >  static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
> >              ^
> > drivers/gpu/drm/i915/intel_runtime_pm.c:386:13: warning: ‘gen9_disable_dc5’ defined but not used [-Wunused-function]
> >  static void gen9_disable_dc5(struct drm_i915_private *dev_priv)
> >              ^
> > 
> > Generally speaking, in a series, each step should compile without warning and
> > result in a working driver (for bisectability).
> 
> Yes, agreed. Splitting the changes into patches could've been done in
> better a way. I also commented on a related topic of adding something in
> the patchset and removing it later. We'll try to pay more attention to
> this in the future.
> 
> Animesh, if you resend this patchset anyway I think you could switch the
> order of 2/8 and 3/8 and add the calls to the above functions in this
> patch to get rid of the warnings. Also please make sure that things
> compile without a warning after each patch as Damien suggested.

Yeah generally I don't like when patches add functions and structures and
don't use them - in the end it's fairly hard to review something if you
don't know how it's getting called used, which means you can't read the
patches linearly. And the point of splitting them is to give reviewers
small digestable chunks instead of the full thing.

Imo it's better to split things the other way round, i.e. wire up stub
functions at first, then fill them out. Instead of the first patch adding
the implementation and the 2nd one wiring things up.
-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] 46+ messages in thread

* Re: ns2501 DVO - success at last
  2015-04-13 19:00             ` ns2501 DVO - success at last Thomas Richter
@ 2015-04-14 17:21               ` Daniel Vetter
  0 siblings, 0 replies; 46+ messages in thread
From: Daniel Vetter @ 2015-04-14 17:21 UTC (permalink / raw)
  To: Thomas Richter; +Cc: intel-gfx

On Mon, Apr 13, 2015 at 09:00:48PM +0200, Thomas Richter wrote:
> Hi Daniel, hi Ville,
> 
> some success at last. I couldn't stop myself playing with the NatSemi 2501
> DVO in my Fujitsu S6010 and I believe I finally got a hang on this chip. I
> believe I understand now most of the undocumented registers.
> 
> There are also a couple of additional features that are, apparently, not
> used by the video BIOS of the S6010, namely the chip has a ditherer on board
> - quite like the Intel Video Controller hub in the IBM R31.
> Unfortunately, to enable the scaler, the bypass must be turned off, and
> hence, parameters for a 1:1 through-mapping of the scaler are required.
> 
> After quite some experimenting, I believe I found now the right settings to
> enable the scaler and configure it to pass the 1024x768 input to the output.
> 
> The chip is really a bit weird. It not only requires the scaling factors,
> but also the input timings, (sync width, front/back porch for both
> horizontal and vertical) and the output timing, and the configuration of its
> PLL to sample the incoming data. Currently, most of the data I obtained by
> "trail and error", at least for the 1024x768 mode in which the bios
> configures the DVO in bypass mode.
> 
> It turned out we forgot to configure a couple of registers (and some others
> are pretty much blank).
> 
> Thus, my question at this time is whether there is any interface how to get
> the precise timing of the loaded video mode from the i915 module directly
> instead of second-guessing the parameters, i.e. dimensions of the frame,
> porch sizes, size of the sync pulses, pixel clock and so on.
> 
> Other than that, I'll try to clean up the code I have to so far in the next
> days and release it.

In the mode structure that gets passed to your dvo driver look for the
crtc_* values, those are the exact timings you need to set up. You want to
look at the adjusted_mode since that's the one that actually gets sent to
the dvo port, the other mode is the one userspace request and will get
munged a bit.

btw the sdvo code works really similar and also has input and output
timings for the transcoder chip. You could peak at that code to see how
it's all done.

Cheers, Daniel

PS: You're replies are still attached to some random thread, which makes
them harder to spot and not miss ...
-- 
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] 46+ messages in thread

end of thread, other threads:[~2015-04-14 17:19 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-01 10:49 [PATCH 0/8] Enable DC states for skl Animesh Manna
2015-04-01 10:52 ` [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware Animesh Manna
2015-04-01 10:52   ` [PATCH 2/8] drm/i915/skl: Implement enable/disable for Display C5 sttate Animesh Manna
2015-04-02 15:58     ` Imre Deak
2015-04-13 13:17       ` Damien Lespiau
2015-04-13 13:51         ` Imre Deak
2015-04-14 11:50           ` Daniel Vetter
2015-04-01 10:52   ` [PATCH 3/8] drm/i915/skl: Add DC5 Trigger Sequence Animesh Manna
2015-04-02 19:33     ` Imre Deak
2015-04-10 15:11       ` [PATCH v2 " Animesh Manna
2015-04-13 10:26         ` [PATCH v3 " Animesh Manna
2015-04-13 11:33           ` Imre Deak
2015-04-13 17:41             ` Damien Lespiau
2015-04-13 15:25           ` Damien Lespiau
2015-04-13 17:49           ` Damien Lespiau
2015-04-01 10:52   ` [PATCH 4/8] drm/i915/skl: Assert the requirements to enter or exit DC5 Animesh Manna
2015-04-02 20:17     ` Imre Deak
2015-04-10 15:11       ` [PATCH v2 " Animesh Manna
2015-04-13 12:46         ` Imre Deak
2015-04-01 10:52   ` [PATCH 5/8] drm/i915/skl: Implement enable/disable for Display C6 state Animesh Manna
2015-04-02 20:20     ` Imre Deak
2015-04-01 10:52   ` [PATCH 6/8] drm/i915/skl: Add DC6 Trigger sequence Animesh Manna
2015-04-02 20:42     ` Imre Deak
2015-04-10 15:11       ` [PATCH v2 " Animesh Manna
2015-04-13 12:50         ` Imre Deak
2015-04-01 10:52   ` [PATCH 7/8] drm/i915/skl: Assert the requirements to enter or exit DC6 Animesh Manna
2015-04-02 20:49     ` Imre Deak
2015-04-10 15:12       ` [PATCH v2 " Animesh Manna
2015-04-01 10:52   ` [PATCH 8/8] drm/i915/skl: Enable runtime PM Animesh Manna
2015-04-02 20:49     ` Imre Deak
2015-04-02 15:21   ` [PATCH 1/8] drm/i915/skl: Add support to load SKL CSR firmware Imre Deak
2015-04-10 15:11     ` [PATCH v2 " Animesh Manna
2015-04-13 10:24       ` [PATCH v3 " Animesh Manna
2015-04-13 11:03         ` Imre Deak
2015-04-13 13:07           ` Animesh Manna
2015-04-13 12:37             ` Imre Deak
2015-04-13 16:34         ` Damien Lespiau
2015-04-13 16:52           ` Imre Deak
2015-04-13 17:02             ` Damien Lespiau
2015-04-13 17:15               ` Imre Deak
2015-04-13 17:22                 ` Damien Lespiau
2015-04-14  9:16                   ` Animesh Manna
2015-04-14 10:07                     ` Damien Lespiau
     [not found]           ` <20804_1428943986_552BF472_20804_13643_1_1428943974.12269.9.camel@ideak-mobl>
2015-04-13 19:00             ` ns2501 DVO - success at last Thomas Richter
2015-04-14 17:21               ` Daniel Vetter
2015-04-10 15:10 ` [PATCH v2 0/8] Enable DC states for skl Animesh Manna

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.