summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display/intel_dmc.c
diff options
context:
space:
mode:
authorJani Nikula <jani.nikula@intel.com>2023-03-01 14:29:43 +0200
committerJani Nikula <jani.nikula@intel.com>2023-03-06 19:09:47 +0200
commite81a3c12b88ab685ce10482c3f6d5aa46f08a6fa (patch)
treef36cb5d8376121a70b96ca58ad4c8ede83dc74f9 /drivers/gpu/drm/i915/display/intel_dmc.c
parent1b28c1c789d0c11be213bb5d892f9a094ab8e201 (diff)
drm/i915/dmc: allocate dmc structure dynamically
sizeof(struct intel_dmc) > 1024 bytes, allocated on all platforms as part of struct drm_i915_private, whether they have DMC or not. Allocate struct intel_dmc dynamically, and hide all the dmc details behind an opaque pointer in intel_dmc.c. Care must be taken to take into account all cases: DMC not supported on the platform, DMC supported but not initialized, and DMC initialized but not loaded. For the second case, we need to move the wakeref out of struct intel_dmc. v2: - Rebase to kzalloc dmc after runtime pm get (Imre) Cc: Imre Deak <imre.deak@intel.com> Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230301122944.1298929-4-jani.nikula@intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dmc.c')
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc.c50
1 files changed, 45 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
index acd792480aba..302a465ceb1f 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -38,9 +38,37 @@
* low-power state and comes back to normal.
*/
+enum intel_dmc_id {
+ DMC_FW_MAIN = 0,
+ DMC_FW_PIPEA,
+ DMC_FW_PIPEB,
+ DMC_FW_PIPEC,
+ DMC_FW_PIPED,
+ DMC_FW_MAX
+};
+
+struct intel_dmc {
+ struct drm_i915_private *i915;
+ struct work_struct work;
+ const char *fw_path;
+ u32 max_fw_size; /* bytes */
+ u32 version;
+ struct dmc_fw_info {
+ u32 mmio_count;
+ i915_reg_t mmioaddr[20];
+ u32 mmiodata[20];
+ u32 dmc_offset;
+ u32 start_mmioaddr;
+ u32 dmc_fw_size; /*dwords */
+ u32 *payload;
+ bool present;
+ } dmc_info[DMC_FW_MAX];
+};
+
+/* Note: This may be NULL. */
static struct intel_dmc *i915_to_dmc(struct drm_i915_private *i915)
{
- return &i915->display.dmc;
+ return i915->display.dmc.dmc;
}
#define DMC_VERSION(major, minor) ((major) << 16 | (minor))
@@ -947,7 +975,10 @@ void intel_dmc_init(struct drm_i915_private *dev_priv)
*/
intel_dmc_runtime_pm_get(dev_priv);
- dmc = i915_to_dmc(dev_priv);
+ dmc = kzalloc(sizeof(*dmc), GFP_KERNEL);
+ if (!dmc)
+ return;
+
dmc->i915 = dev_priv;
INIT_WORK(&dmc->work, dmc_load_work_fn);
@@ -991,10 +1022,9 @@ void intel_dmc_init(struct drm_i915_private *dev_priv)
if (dev_priv->params.dmc_firmware_path) {
if (strlen(dev_priv->params.dmc_firmware_path) == 0) {
- dmc->fw_path = NULL;
drm_info(&dev_priv->drm,
"Disabling DMC firmware and runtime PM\n");
- return;
+ goto out;
}
dmc->fw_path = dev_priv->params.dmc_firmware_path;
@@ -1003,11 +1033,18 @@ void intel_dmc_init(struct drm_i915_private *dev_priv)
if (!dmc->fw_path) {
drm_dbg_kms(&dev_priv->drm,
"No known DMC firmware for platform, disabling runtime PM\n");
- return;
+ goto out;
}
+ dev_priv->display.dmc.dmc = dmc;
+
drm_dbg_kms(&dev_priv->drm, "Loading %s\n", dmc->fw_path);
schedule_work(&dmc->work);
+
+ return;
+
+out:
+ kfree(dmc);
}
/**
@@ -1074,6 +1111,9 @@ void intel_dmc_fini(struct drm_i915_private *dev_priv)
if (dmc) {
for_each_dmc_id(dmc_id)
kfree(dmc->dmc_info[dmc_id].payload);
+
+ kfree(dmc);
+ dev_priv->display.dmc.dmc = NULL;
}
}