drm/i915/csr: Allow matching unknown HW steppings with generic firmware
If the firmware is generic and has a run-anywhere mode, enable it rather than completely failing on unknown HW revisions. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Damien Lespiau <damien.lespiau@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Sunil Kamath <sunil.kamath@intel.com> Cc: Daniel Vetter <daniel.vetter@intel.com> Cc: Animesh Manna <animesh.manna@intel.com> Cc: Jani Nikula <jani.nikula@intel.com> Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1457352357-8433-1-git-send-email-chris@chris-wilson.co.uk
This commit is contained in:
parent
7cc96139d9
commit
1bb4308e71
|
@ -188,28 +188,31 @@ static const struct stepping_info bxt_stepping_info[] = {
|
||||||
{'B', '0'}, {'B', '1'}, {'B', '2'}
|
{'B', '0'}, {'B', '1'}, {'B', '2'}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct stepping_info *intel_get_stepping_info(struct drm_device *dev)
|
static const struct stepping_info no_stepping_info = { '*', '*' };
|
||||||
|
|
||||||
|
static const struct stepping_info *
|
||||||
|
intel_get_stepping_info(struct drm_i915_private *dev_priv)
|
||||||
{
|
{
|
||||||
const struct stepping_info *si;
|
const struct stepping_info *si;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
|
|
||||||
if (IS_KABYLAKE(dev)) {
|
if (IS_KABYLAKE(dev_priv)) {
|
||||||
size = ARRAY_SIZE(kbl_stepping_info);
|
size = ARRAY_SIZE(kbl_stepping_info);
|
||||||
si = kbl_stepping_info;
|
si = kbl_stepping_info;
|
||||||
} else if (IS_SKYLAKE(dev)) {
|
} else if (IS_SKYLAKE(dev_priv)) {
|
||||||
size = ARRAY_SIZE(skl_stepping_info);
|
size = ARRAY_SIZE(skl_stepping_info);
|
||||||
si = skl_stepping_info;
|
si = skl_stepping_info;
|
||||||
} else if (IS_BROXTON(dev)) {
|
} else if (IS_BROXTON(dev_priv)) {
|
||||||
size = ARRAY_SIZE(bxt_stepping_info);
|
size = ARRAY_SIZE(bxt_stepping_info);
|
||||||
si = bxt_stepping_info;
|
si = bxt_stepping_info;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (INTEL_REVID(dev) < size)
|
if (INTEL_REVID(dev_priv) < size)
|
||||||
return si + INTEL_REVID(dev);
|
return si + INTEL_REVID(dev_priv);
|
||||||
|
|
||||||
return NULL;
|
return &no_stepping_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
|
static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
|
||||||
|
@ -270,13 +273,11 @@ void intel_csr_load_program(struct drm_i915_private *dev_priv)
|
||||||
static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
|
static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
|
||||||
const struct firmware *fw)
|
const struct firmware *fw)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = dev_priv->dev;
|
|
||||||
struct intel_css_header *css_header;
|
struct intel_css_header *css_header;
|
||||||
struct intel_package_header *package_header;
|
struct intel_package_header *package_header;
|
||||||
struct intel_dmc_header *dmc_header;
|
struct intel_dmc_header *dmc_header;
|
||||||
struct intel_csr *csr = &dev_priv->csr;
|
struct intel_csr *csr = &dev_priv->csr;
|
||||||
const struct stepping_info *stepping_info = intel_get_stepping_info(dev);
|
const struct stepping_info *si = intel_get_stepping_info(dev_priv);
|
||||||
char stepping, substepping;
|
|
||||||
uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
|
uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t *dmc_payload;
|
uint32_t *dmc_payload;
|
||||||
|
@ -284,14 +285,6 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
|
||||||
if (!fw)
|
if (!fw)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!stepping_info) {
|
|
||||||
DRM_ERROR("Unknown stepping info, firmware loading failed\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
stepping = stepping_info->stepping;
|
|
||||||
substepping = stepping_info->substepping;
|
|
||||||
|
|
||||||
/* Extract CSS Header information*/
|
/* Extract CSS Header information*/
|
||||||
css_header = (struct intel_css_header *)fw->data;
|
css_header = (struct intel_css_header *)fw->data;
|
||||||
if (sizeof(struct intel_css_header) !=
|
if (sizeof(struct intel_css_header) !=
|
||||||
|
@ -303,7 +296,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
|
||||||
|
|
||||||
csr->version = css_header->version;
|
csr->version = css_header->version;
|
||||||
|
|
||||||
if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
|
if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
|
||||||
csr->version < SKL_CSR_VERSION_REQUIRED) {
|
csr->version < SKL_CSR_VERSION_REQUIRED) {
|
||||||
DRM_INFO("Refusing to load old Skylake DMC firmware v%u.%u,"
|
DRM_INFO("Refusing to load old Skylake DMC firmware v%u.%u,"
|
||||||
" please upgrade to v%u.%u or later"
|
" please upgrade to v%u.%u or later"
|
||||||
|
@ -331,11 +324,11 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
|
||||||
/* Search for dmc_offset to find firware binary. */
|
/* Search for dmc_offset to find firware binary. */
|
||||||
for (i = 0; i < package_header->num_entries; i++) {
|
for (i = 0; i < package_header->num_entries; i++) {
|
||||||
if (package_header->fw_info[i].substepping == '*' &&
|
if (package_header->fw_info[i].substepping == '*' &&
|
||||||
stepping == package_header->fw_info[i].stepping) {
|
si->stepping == package_header->fw_info[i].stepping) {
|
||||||
dmc_offset = package_header->fw_info[i].offset;
|
dmc_offset = package_header->fw_info[i].offset;
|
||||||
break;
|
break;
|
||||||
} else if (stepping == package_header->fw_info[i].stepping &&
|
} else if (si->stepping == package_header->fw_info[i].stepping &&
|
||||||
substepping == package_header->fw_info[i].substepping) {
|
si->substepping == package_header->fw_info[i].substepping) {
|
||||||
dmc_offset = package_header->fw_info[i].offset;
|
dmc_offset = package_header->fw_info[i].offset;
|
||||||
break;
|
break;
|
||||||
} else if (package_header->fw_info[i].stepping == '*' &&
|
} else if (package_header->fw_info[i].stepping == '*' &&
|
||||||
|
@ -343,7 +336,8 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
|
||||||
dmc_offset = package_header->fw_info[i].offset;
|
dmc_offset = package_header->fw_info[i].offset;
|
||||||
}
|
}
|
||||||
if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
|
if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
|
||||||
DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
|
DRM_ERROR("Firmware not supported for %c stepping\n",
|
||||||
|
si->stepping);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
readcount += dmc_offset;
|
readcount += dmc_offset;
|
||||||
|
@ -389,9 +383,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(dmc_payload, &fw->data[readcount], nbytes);
|
return memcpy(dmc_payload, &fw->data[readcount], nbytes);
|
||||||
|
|
||||||
return dmc_payload;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void csr_load_work_fn(struct work_struct *work)
|
static void csr_load_work_fn(struct work_struct *work)
|
||||||
|
|
Loading…
Reference in New Issue