Skip to content

Commit eb80562

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

File tree

6 files changed

+420
-3
lines changed

6 files changed

+420
-3
lines changed

drivers/gpu/drm/i915/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ i915-y := i915_drv.o \
1212
i915_suspend.o \
1313
i915_sysfs.o \
1414
intel_pm.o \
15-
intel_runtime_pm.o
15+
intel_runtime_pm.o \
16+
intel_csr.o
1617

1718
i915-$(CONFIG_COMPAT) += i915_ioc32.o
1819
i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o

drivers/gpu/drm/i915/i915_dma.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
816816
spin_lock_init(&dev_priv->mmio_flip_lock);
817817
mutex_init(&dev_priv->dpio_lock);
818818
mutex_init(&dev_priv->modeset_restore_lock);
819+
mutex_init(&dev_priv->csr_lock);
819820

820821
intel_pm_setup(dev);
821822

@@ -861,9 +862,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
861862

862863
intel_uncore_init(dev);
863864

865+
/* Load CSR Firmware for SKL */
866+
intel_csr_ucode_init(dev);
867+
864868
ret = i915_gem_gtt_init(dev);
865869
if (ret)
866-
goto out_regs;
870+
goto out_freecsr;
867871

868872
/* WARNING: Apparently we must kick fbdev drivers before vgacon,
869873
* otherwise the vga fbdev driver falls over. */
@@ -1033,7 +1037,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
10331037
io_mapping_free(dev_priv->gtt.mappable);
10341038
out_gtt:
10351039
i915_global_gtt_cleanup(dev);
1036-
out_regs:
1040+
out_freecsr:
1041+
intel_csr_ucode_fini(dev);
10371042
intel_uncore_fini(dev);
10381043
pci_iounmap(dev->pdev, dev_priv->regs);
10391044
put_bridge:
@@ -1113,6 +1118,8 @@ int i915_driver_unload(struct drm_device *dev)
11131118
mutex_unlock(&dev->struct_mutex);
11141119
i915_gem_cleanup_stolen(dev);
11151120

1121+
intel_csr_ucode_fini(dev);
1122+
11161123
intel_teardown_gmbus(dev);
11171124
intel_teardown_mchbar(dev);
11181125

drivers/gpu/drm/i915/i915_drv.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,26 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
556556
cancel_delayed_work_sync(&dev_priv->hotplug_reenable_work);
557557
}
558558

559+
void i915_firmware_load_error_print(const char *fw_path, int err)
560+
{
561+
DRM_ERROR("failed to load firmware %s (%d)\n", fw_path, err);
562+
563+
/*
564+
* If the reason is not known assume -ENOENT since that's the most
565+
* usual failure mode.
566+
*/
567+
if (!err)
568+
err = -ENOENT;
569+
570+
if (!(IS_BUILTIN(CONFIG_DRM_I915) && err == -ENOENT))
571+
return;
572+
573+
DRM_ERROR(
574+
"The driver is built-in, so to load the firmware you need to\n"
575+
"include it either in the kernel (see CONFIG_EXTRA_FIRMWARE) or\n"
576+
"in your initrd/initramfs image.\n");
577+
}
578+
559579
static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
560580
{
561581
struct drm_device *dev = dev_priv->dev;

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,15 @@ struct intel_uncore {
669669
#define for_each_fw_domain(domain__, dev_priv__, i__) \
670670
for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
671671

672+
struct intel_csr {
673+
const char *fw_path;
674+
__be32 *dmc_payload;
675+
uint32_t dmc_fw_size;
676+
uint32_t mmio_count;
677+
uint32_t mmioaddr[8];
678+
uint32_t mmiodata[8];
679+
};
680+
672681
#define DEV_INFO_FOR_EACH_FLAG(func, sep) \
673682
func(is_mobile) sep \
674683
func(is_i85x) sep \
@@ -1574,6 +1583,11 @@ struct drm_i915_private {
15741583

15751584
struct i915_virtual_gpu vgpu;
15761585

1586+
struct intel_csr csr;
1587+
1588+
/* Display CSR-related protection */
1589+
struct mutex csr_lock;
1590+
15771591
struct intel_gmbus gmbus[GMBUS_NUM_PINS];
15781592

15791593
/** gmbus_mutex protects against concurrent usage of the single hw gmbus
@@ -2426,6 +2440,8 @@ struct drm_i915_cmd_table {
24262440
#define HAS_RC6(dev) (INTEL_INFO(dev)->gen >= 6)
24272441
#define HAS_RC6p(dev) (INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
24282442

2443+
#define HAS_CSR(dev) (IS_SKYLAKE(dev))
2444+
24292445
#define INTEL_PCH_DEVICE_ID_MASK 0xff00
24302446
#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
24312447
#define INTEL_PCH_CPT_DEVICE_ID_TYPE 0x1c00
@@ -2516,6 +2532,7 @@ extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
25162532
extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
25172533
int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
25182534
void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
2535+
void i915_firmware_load_error_print(const char *fw_path, int err);
25192536

25202537
/* i915_irq.c */
25212538
void i915_queue_hangcheck(struct drm_device *dev);

0 commit comments

Comments
 (0)