Skip to content

Commit

Permalink
drm/i915: Ignore OpRegion panel type unless the "override" bit is set
Browse files Browse the repository at this point in the history
While commit a056281 ("drm/i915: Get panel_type from OpRegion panel
details") fixed the original GM45 machine, it has apparently regressed
many more machines. Damned if you do, damned if you don't it seems :(

The only glimmer of hope I see in the spec is the "override" bit in the
SCIC response.  The spec is super unclear about the meaning of the this
bit, but perhaps if the bit is zero, we're supposed to ignore the panel
type? At least the bit has been zero in all the logs I've received from
the failing machines. What I don't know yet is what the original GM45
machine that needs the panel type from OpRegion has there. Let's try it.

Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Rob Kramer <rob@solution-space.com>
Cc: Martin van Es <martin@mrvanes.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Dave Airlie <airlied@linux.ie>
Cc: Marco Krüger <krgsch@gmail.com>
Cc: Sean Greenslade <sean@seangreenslade.com>
Cc: Trudy Tective <bertslany@gmail.com>
Cc: Robin Müller <rm1990@gmx.de>
Cc: Alexander Kobel <a-kobel@a-kobel.de>
References: https://lists.freedesktop.org/archives/intel-gfx/2016-August/105545.html
References: https://lists.freedesktop.org/archives/dri-devel/2016-August/116888.html
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94825
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97060
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97443
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97363
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
  • Loading branch information
vsyrjala committed Sep 6, 2016
1 parent f0ddbd8 commit 4ff3907
Showing 1 changed file with 18 additions and 8 deletions.
26 changes: 18 additions & 8 deletions drivers/gpu/drm/i915/intel_opregion.c
Expand Up @@ -258,7 +258,8 @@ struct opregion_asle_ext {
#define MAX_DSLP 1500

static int swsci(struct drm_i915_private *dev_priv,
u32 function, u32 parm, u32 *parm_out)
u32 function, u32 parm,
u32 *scic_out, u32 *parm_out)
{
struct opregion_swsci *swsci = dev_priv->opregion.swsci;
struct pci_dev *pdev = dev_priv->drm.pdev;
Expand Down Expand Up @@ -332,6 +333,9 @@ static int swsci(struct drm_i915_private *dev_priv,
return -ETIMEDOUT;
}

if (scic_out)
*scic_out = scic;

scic = (scic & SWSCI_SCIC_EXIT_STATUS_MASK) >>
SWSCI_SCIC_EXIT_STATUS_SHIFT;

Expand Down Expand Up @@ -409,7 +413,7 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,

parm |= type << (16 + port * 3);

return swsci(dev_priv, SWSCI_SBCB_DISPLAY_POWER_STATE, parm, NULL);
return swsci(dev_priv, SWSCI_SBCB_DISPLAY_POWER_STATE, parm, NULL, NULL);
}

static const struct {
Expand All @@ -434,7 +438,7 @@ int intel_opregion_notify_adapter(struct drm_i915_private *dev_priv,
for (i = 0; i < ARRAY_SIZE(power_state_map); i++) {
if (state == power_state_map[i].pci_power_state)
return swsci(dev_priv, SWSCI_SBCB_ADAPTER_POWER_STATE,
power_state_map[i].parm, NULL);
power_state_map[i].parm, NULL, NULL);
}

return -EINVAL;
Expand Down Expand Up @@ -897,7 +901,7 @@ static void swsci_setup(struct drm_i915_private *dev_priv)
opregion->swsci_sbcb_sub_functions = 1;

/* We use GBDA to ask for supported GBDA calls. */
if (swsci(dev_priv, SWSCI_GBDA_SUPPORTED_CALLS, 0, &tmp) == 0) {
if (swsci(dev_priv, SWSCI_GBDA_SUPPORTED_CALLS, 0, NULL, &tmp) == 0) {
/* make the bits match the sub-function codes */
tmp <<= 1;
opregion->swsci_gbda_sub_functions |= tmp;
Expand All @@ -908,7 +912,7 @@ static void swsci_setup(struct drm_i915_private *dev_priv)
* must not call interfaces that are not specifically requested by the
* bios.
*/
if (swsci(dev_priv, SWSCI_GBDA_REQUESTED_CALLBACKS, 0, &tmp) == 0) {
if (swsci(dev_priv, SWSCI_GBDA_REQUESTED_CALLBACKS, 0, NULL, &tmp) == 0) {
/* here, the bits already match sub-function codes */
opregion->swsci_sbcb_sub_functions |= tmp;
requested_callbacks = true;
Expand All @@ -919,7 +923,7 @@ static void swsci_setup(struct drm_i915_private *dev_priv)
* the callback is _requested_. But we still can't call interfaces that
* are not requested.
*/
if (swsci(dev_priv, SWSCI_SBCB_SUPPORTED_CALLBACKS, 0, &tmp) == 0) {
if (swsci(dev_priv, SWSCI_SBCB_SUPPORTED_CALLBACKS, 0, NULL, &tmp) == 0) {
/* make the bits match the sub-function codes */
u32 low = tmp & 0x7ff;
u32 high = tmp & ~0xfff; /* bit 11 is reserved */
Expand Down Expand Up @@ -1059,16 +1063,22 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
int
intel_opregion_get_panel_type(struct drm_i915_private *dev_priv)
{
u32 panel_details;
u32 panel_scic, panel_details;
int ret;

ret = swsci(dev_priv, SWSCI_GBDA_PANEL_DETAILS, 0x0, &panel_details);
ret = swsci(dev_priv, SWSCI_GBDA_PANEL_DETAILS, 0x0,
&panel_scic, &panel_details);
if (ret) {
DRM_DEBUG_KMS("Failed to get panel details from OpRegion (%d)\n",
ret);
return ret;
}

if ((panel_scic & (1 << 8)) == 0) {
DRM_DEBUG_KMS("No OpRegion panel type override\n");
return -ENODEV;
}

ret = (panel_details >> 8) & 0xff;
if (ret > 0x10) {
DRM_DEBUG_KMS("Invalid OpRegion panel type 0x%x\n", ret);
Expand Down

0 comments on commit 4ff3907

Please sign in to comment.