@@ -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
@@ -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);
@@ -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;
@@ -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);
@@ -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,